home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus Special 25 / AMIGAplus Sonderheft 25 (2000)(Falke)(DE)(Track 1 of 4)[!].iso / PublicDomain / Spiele / WormWars / Source / system.c < prev    next >
C/C++ Source or Header  |  2000-04-26  |  111KB  |  3,626 lines

  1. /* $Filename: WormWars/Source/system.c $
  2.  * $VER:      Worm Wars 5.61 for Amiga $
  3.  *
  4.  * © Copyright 2000 James R. Jacobs. Freely distributable.
  5.  *        _
  6.  *       //        -=AMIGA=-
  7.  *      //
  8.  * _   //
  9.  * \\ //
  10.  *  \X/
  11.  
  12. #INCLUDES ---------------------------------------------------------------- */
  13.  
  14. #include "system.h" /* #includes everything else */
  15.  
  16. /* PROTOTYPES (Amiga-only) ----------------------------------------------- */
  17.  
  18. MODULE void freefx(void);
  19. MODULE void helpabout(void);
  20. MODULE void helploop(void);
  21. MODULE void helpmanual(void);
  22. MODULE void loadthefx(void);
  23. MODULE void loadthemusic(void);
  24. MODULE void parsewb(void);
  25. MODULE void pausetimer(void);
  26. MODULE void unpausetimer(void);
  27.  
  28. MODULE void dot(SBYTE x, SBYTE y);
  29. MODULE void help(UBYTE type);
  30. MODULE void preserve(SWORD x, SBYTE row, SBYTE image, UWORD amount);
  31. MODULE void setpointer(SBYTE brush);
  32. MODULE void toggle(SBYTE key);
  33. MODULE void underline(SBYTE brush);
  34.  
  35. MODULE ABOOL beginfx(void);
  36. MODULE UBYTE ReadJoystick(UWORD joynum);
  37. MODULE SWORD xpixeltosquare(SWORD x);
  38. MODULE SWORD ypixeltosquare(SWORD y);
  39.  
  40. /* EXTERNAL VARIABLES (owned by engine.c, imported by system.c) ----------- */
  41.  
  42. IMPORT    struct Library*            SysBase;
  43.  
  44. IMPORT    ABOOL                    clearthem, modified;
  45. IMPORT    SBYTE                    a, board[MAXLEVELS + 1][FIELDX + 1][FIELDY + 1],
  46.                                 eachworm[4][2][9],
  47.                                 field[FIELDX + 1][FIELDY + 1],
  48.                                 level, levels, players,
  49.                                 startx[MAXLEVELS + 1], starty[MAXLEVELS + 1];
  50. IMPORT    SWORD                    secondsleft, secondsperlevel;
  51. IMPORT    ULONG                    delay, r;
  52. IMPORT    struct HiScoreStruct    hiscore[HISCORES + 1];
  53. IMPORT    struct TeleportStruct    teleport[MAXLEVELS + 1][4];
  54. IMPORT    struct WormStruct       worm[4];
  55. IMPORT    TEXT                    pathname[81],
  56.                                 date[DATELENGTH + 1],
  57.                                 times[TIMELENGTH + 1];
  58.  
  59. /* MODULE VARIABLES (used only within system.c) --------------------------- */
  60.  
  61. AGLOBAL struct Library*         TimerBase;
  62. MODULE    struct ASLBase*         ASLBase       = NULL;
  63. MODULE    struct DiskFontBase*    DiskFontBase  = NULL;
  64. MODULE    struct GadToolsBase*    GadToolsBase  = NULL;
  65. MODULE    struct GfxBase*         GfxBase       = NULL;
  66. MODULE    struct Library*        IconBase      = NULL;
  67. MODULE    struct IntuitionBase*    IntuitionBase = NULL;
  68. MODULE    struct MEDPlayerBase*    MEDPlayerBase = NULL;
  69. MODULE    struct UtilityBase*     UtilityBase   = NULL;
  70.  
  71. MODULE  ABOOL  eversent[4],
  72.                icons        = TRUE,
  73.                ignore       = FALSE,
  74.                iso          = TRUE,
  75.                joy          = FALSE,
  76.                sticky       = FALSE;
  77. MODULE  SBYTE  AudioClosed  = TRUE,
  78.                brush        = STONE,
  79.                Controller   = GPCT_NOCONTROLLER,
  80.                JoyClosed    = TRUE,
  81.                OldPri       = 0,
  82.                TimerClosed  = TRUE;
  83. MODULE  UBYTE  fxable       = 2,
  84.                mode         = NULL;
  85.                musicable    = 2;
  86. MODULE    ULONG  fsize,
  87.                receipter[4] = {(ULONG) -1, (ULONG) -1, (ULONG) -1, (ULONG) -1};
  88. MODULE    UBYTE* fbase        = NULL;
  89. MODULE    BPTR   FilePtr      = NULL;
  90. MODULE  APTR   OldWindowPtr = NULL;
  91. MODULE    SWORD  pixy;
  92.  
  93. MODULE    struct InputEvent     GameEvent;
  94. MODULE    struct TextAttr       WormWars8 =
  95. {    (STRPTR) "WormWars.font", 8, FS_NORMAL, FPF_DISKFONT | FPF_DESIGNED
  96. },                            Topaz8 =
  97. {    (STRPTR) "topaz.font", 8, FS_NORMAL, FPF_ROMFONT | FPF_DESIGNED
  98. };
  99.  
  100. MODULE    struct Gadget         *CheckboxGadgetPtr  = NULL,
  101.                               *CycleGadgetPtr[4]  = {NULL, NULL, NULL, NULL},
  102.                               *GListPtr           = NULL,
  103.                               *PrevGadgetPtr      = NULL,
  104.                               *StringGadgetPtr[5] = {NULL, NULL, NULL, NULL, NULL};
  105. MODULE    struct MsgPort        *AudioPortPtr[4]    = {NULL, NULL, NULL, NULL},
  106.                               *JoyPortPtr         = NULL,
  107.                               *TimerPortPtr       = NULL;
  108. MODULE    struct timeval        *CurrentValPtr      = NULL,
  109.                               *PausedValPtr       = NULL,
  110.                               *StartValPtr        = NULL;
  111. MODULE    struct Window         *HelpWindowPtr      = NULL,
  112.                               *MainWindowPtr      = NULL;
  113.  
  114. MODULE  struct CIA*           CIAPtr              = (struct CIA *) 0xBFE001;
  115. MODULE    struct RDArgs*        ArgsPtr             = NULL;
  116. MODULE    struct FileRequester* ASLRqPtr            = NULL;
  117. MODULE    struct IOAudio*       AudioRqPtr[4]       = {NULL, NULL, NULL, NULL};
  118. MODULE    struct TextFont*      FontPtr             = NULL;
  119. MODULE    struct IOStdReq*      JoyRqPtr            = NULL;
  120. MODULE    struct Menu*          MenuPtr             = NULL;
  121. MODULE    struct Process*       ProcessPtr          = NULL;
  122. MODULE    struct Screen*        ScreenPtr           = NULL;
  123. MODULE    struct MMD0*          SongPtr             = NULL;
  124. MODULE    struct timerequest*   TimerRqPtr          = NULL;
  125. MODULE    struct VisualInfo*    VisualInfoPtr       = NULL;
  126. MODULE    struct WBArg*         WBArg               = NULL;
  127. MODULE    struct WBStartup*     WBMsg               = NULL;
  128.  
  129. /* FUNCTIONS -------------------------------------------------------------- */
  130.  
  131. int main(int argc, char** argv)
  132. {
  133. BPTR                OldDir;
  134. SLONG                i;
  135. ABOOL                success                    = FALSE;
  136. SBYTE                error                    = 0,
  137.                                 player, which;
  138. TEXT                saystring[SAYLIMIT + 1];
  139. SWORD                           oldsecondsleft;
  140. UWORD                Pens[10] =
  141. {    BLACK,        /* DETAILPEN        text in title bar */
  142.     WHITE,        /* BLOCKPEN            fill title bar */
  143.     WHITE,        /* TEXTPEN            regular text on BACKGROUNDPEN */
  144.     LIGHTGREY,    /* SHINEPEN            bright edge */
  145.     DARKGREY,    /* SHADOWPEN        dark edge */
  146.     PURPLE,        /* FILLPEN            filling active window borders
  147.                                     and selected gadgets */
  148.     BLACK,        /* FILLTEXTPEN        text rendered over FILLPEN */
  149.     BLACK,        /* BACKGROUNDPEN    background colour */
  150.     RED,        /* HIGHLIGHTTEXTPEN    highlighted text on BACKGROUNDPEN */
  151.     (UWORD) ~0    /* and used against BLOCKPEN in ASL save requesters */
  152. };
  153. SLONG                args[10]                = {0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L};
  154. struct ColorSpec    Colours[21] =
  155. {   /* colour   red   green   blue   description */
  156.     {   0,      0x0,    0x0,    0x0},   /*        BLACK */
  157.     {   1,      0xF,    0xF,    0xF},   /*        WHITE */
  158.     {   2,      0x4,    0x4,    0x4},   /*    DARKGREY */
  159.     {   3,      0x6,    0x6,    0x6},   /*  MEDIUMGREY */
  160.     {   4,      0xA,    0xA,    0xA},   /*   LIGHTGREY */
  161.     {   5,      0x0,    0x0,    0x0},   /*        black */
  162.     {   6,      0xA,    0x2,    0xA},   /*        PURPLE */
  163.     {   7,      0x8,    0x4,    0x2},   /*        brown */
  164.     {   8,      0x3,    0x9,    0x3},   /*    DARKGREEN */
  165.     {   9,      0x4,    0xE,    0x4},   /*  light GREEN */
  166.     {   10,     0xF,    0x1,    0x1},   /*    DARKRED */
  167.     {   11,     0xF,    0x5,    0x5},   /*  light RED */
  168.     {   12,     0x3,    0x3,    0xF},   /*    DARKBLUE */
  169.     {   13,     0x6,    0x6,    0xF},   /*  light BLUE */
  170.     {   14,     0xA,    0x8,    0x3},   /*    DARKYELLOW */
  171.     {   15,     0xC,    0xC,    0x2},   /*  light YELLOW */
  172.     {   16,     0x0,    0x0,    0x0},   /* pointer: transparent */
  173.     {   17,     0xE,    0x4,    0x4},   /* pointer: fill */
  174.     {   18,     0x3,    0x3,    0x3},   /* pointer: shadow */
  175.     {   19,     0xC,    0xC,    0xC},   /* pointer: shine */
  176.     {   -1,     NULL,   NULL,   NULL
  177. }   };
  178.  
  179. /* Start of program.
  180.  
  181. version embedding into executable */
  182.  
  183. if (0) /* that is, never */
  184.     say(VERSION, ANYTHING);
  185.  
  186. if (!(IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library", 37L)))
  187. {    Write(Output(), OLDKICKSTART, strlen(OLDKICKSTART));
  188.     cleanexit(EXIT_FAILURE);
  189. }
  190.  
  191. /* From this point onwards, we can be sure we have Kickstart 2.04+... */
  192.  
  193. for (i = 0; i <= SAMPLES; i++)
  194.     samp[i].base = NULL;
  195. enginesetup();
  196. ProcessPtr = (struct Process *) FindTask(NULL);
  197.  
  198. if (SysBase->lib_Version < 36L)
  199. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Need exec.library V36+!\0", 24);
  200.     cleanexit(EXIT_FAILURE);
  201. }
  202. if (!(GfxBase = (struct GfxBase *) OpenLibrary("graphics.library", 0L)))
  203. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open graphics.library!\0", 24);
  204.     cleanexit(EXIT_FAILURE);
  205. }
  206. if (!(GadToolsBase = (struct GadToolsBase *) OpenLibrary("gadtools.library", 37L)))
  207. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open GadTools.library V37+!\0", 24);
  208.     cleanexit(EXIT_FAILURE);
  209. }
  210. if (!(ASLBase = (struct ASLBase *) OpenLibrary("asl.library", 0L)))
  211. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open ASL.library!\0", 24);
  212.     cleanexit(EXIT_FAILURE);
  213. }
  214. if (!(UtilityBase = (struct UtilityBase *) OpenLibrary("utility.library", 0L)))
  215. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open utility.library!\0", 24);
  216.     cleanexit(EXIT_FAILURE);
  217. }
  218. if (!(IconBase = (struct Library *) OpenLibrary("icon.library", 0L)))
  219. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open icon.library!\0", 24);
  220.         cleanexit(EXIT_FAILURE);
  221. }
  222.  
  223. /* argument parsing */
  224.  
  225. if (argc) /* started from CLI */
  226. {    if (!(ArgsPtr = ReadArgs
  227.     (    "-F=NOFX/S,-M=NOMUSIC/S,-I=NOICONS/S,-P=PRI/K/N,-O=OVERHEAD/S,"
  228.         "GREEN/K,RED/K,BLUE/K,YELLOW/K,FILE",
  229.         args,
  230.         NULL
  231.     )))
  232.     {    Printf
  233.         (   "Usage: %s [-f=NOFX] [-m=NOMUSIC] [-i=NOICONS]\n"
  234.             "[-p=PRI <priority>] [-o=OVERHEAD] [GREEN=HUMAN|AMIGA|NONE]\n"
  235.             "[RED=HUMAN|AMIGA|NONE] [BLUE=HUMAN|AMIGA|NONE]\n"
  236.             "[YELLOW=HUMAN|AMIGA|NONE] [[FILE=]<fieldset>]\n",
  237.             argv[0]
  238.         );
  239.         cleanexit(EXIT_FAILURE);
  240.     }
  241.     if (args[0])
  242.         fxable = 3;
  243.     if (args[1])
  244.         musicable = 3;
  245.     if (args[2])
  246.         icons = FALSE;
  247.     if (args[3])
  248.     {    if (args[3] < -128 || args[3] > 5)
  249.            {   Printf("%s: Priority range is -128 to +5\n", argv[0]);
  250.                cleanexit(EXIT_FAILURE);
  251.          }
  252.         OldPri = SetTaskPri((struct Task *) ProcessPtr, args[3]);
  253.     }
  254.     if (args[4])
  255.         iso = FALSE;
  256.     if (args[5])
  257.     {    if (!stricmp(args[5], "HUMAN"))
  258.             worm[0].control = HUMAN;
  259.         elif (!stricmp(args[5], "AMIGA"))
  260.             worm[0].control = AMIGA;
  261.         elif (!stricmp(args[5], "NONE"))
  262.             worm[0].control = NONE;
  263.         else
  264.         {    Printf("%s: Green worm control must be HUMAN, AMIGA or NONE\n", argv[0]);
  265.             cleanexit(EXIT_FAILURE);
  266.     }    }
  267.     if (args[6])
  268.     {    if (!stricmp(args[6], "HUMAN"))
  269.             worm[1].control = HUMAN;
  270.         elif (!stricmp(args[6], "AMIGA"))
  271.             worm[1].control = AMIGA;
  272.         elif (!stricmp(args[6], "NONE"))
  273.             worm[1].control = NONE;
  274.         else
  275.         {    Printf("%s: Red worm control must be HUMAN, AMIGA or NONE\n", argv[0]);
  276.             cleanexit(EXIT_FAILURE);
  277.     }    }
  278.     if (args[7])
  279.     {    if (!stricmp(args[7], "HUMAN"))
  280.             worm[2].control = HUMAN;
  281.         elif (!stricmp(args[7], "AMIGA"))
  282.             worm[2].control = AMIGA;
  283.         elif (!stricmp(args[7], "NONE"))
  284.             worm[2].control = NONE;
  285.         else
  286.         {    Printf("%s: Blue worm control must be HUMAN, AMIGA or NONE\n", argv[0]);
  287.             cleanexit(EXIT_FAILURE);
  288.     }    }
  289.     if (args[8])
  290.     {    if (!stricmp(args[8], "HUMAN"))
  291.             worm[3].control = HUMAN;
  292.         elif (!stricmp(args[8], "AMIGA"))
  293.             worm[3].control = AMIGA;
  294.         elif (!stricmp(args[8], "NONE"))
  295.             worm[3].control = NONE;
  296.         else
  297.         {    Printf("%s: Yellow worm control must be HUMAN, AMIGA or NONE\n", argv[0]);
  298.             cleanexit(EXIT_FAILURE);
  299.     }    }
  300.     if (args[9])
  301.         strcpy(pathname, args[9]);
  302. }
  303. else /* started from WB */
  304. {    WBMsg = (struct WBStartup *) argv;
  305.     WBArg = WBMsg->sm_ArgList; /* head of the arg list */
  306.  
  307.     for (i = 0;
  308.          i < WBMsg->sm_NumArgs;
  309.          i++, WBArg++)
  310.     {    if (WBArg->wa_Lock)
  311.         {    /* something that does not support locks */
  312.             parsewb();
  313.         }
  314.         else
  315.         {    /* locks supported, change to the proper directory */
  316.             OldDir = CurrentDir(WBArg->wa_Lock);
  317.             parsewb();
  318.             CurrentDir(OldDir);
  319.                 }
  320.                 if (i == 1)
  321.                         strcpy(pathname, WBArg->wa_Name);
  322. }    }
  323.  
  324. if (!(DiskFontBase = (struct DiskFontBase *) OpenLibrary("diskfont.library", 0L)))
  325.     error = 1;
  326.     
  327. if
  328. (       (!(StartValPtr = (struct timeval *) AllocMem(sizeof(struct timeval), MEMF_PUBLIC | MEMF_CLEAR)))
  329. ||      (!(CurrentValPtr = (struct timeval *) AllocMem(sizeof(struct timeval), MEMF_PUBLIC | MEMF_CLEAR)))
  330. ||      (!(PausedValPtr = (struct timeval *) AllocMem(sizeof(struct timeval), MEMF_PUBLIC | MEMF_CLEAR)))
  331. )
  332. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't allocate timer value structure!\0", 24);
  333.     cleanexit(EXIT_FAILURE);
  334. }
  335. if (!(TimerPortPtr = (struct MsgPort *) CreateMsgPort()))
  336. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't allocate timer message port!\0", 24);
  337.     cleanexit(EXIT_FAILURE);
  338. }
  339. if (!(TimerRqPtr = (struct timerequest *) CreateIORequest(TimerPortPtr, sizeof(struct timerequest))))
  340. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create timer I/O request!\0", 24);
  341.     cleanexit(EXIT_FAILURE);
  342. }
  343. if (TimerClosed = OpenDevice(TIMERNAME, UNIT_VBLANK, TimerRqPtr, 0))
  344. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open timer.device!\0", 24);
  345.     cleanexit(EXIT_FAILURE);
  346. }
  347. TimerBase = (struct Library *) TimerRqPtr->tr_node.io_Device;
  348.  
  349. /* PREPARE DISPLAY -----------------------------------------------
  350.  
  351. font and screen */
  352.  
  353. if ((!error) && (FontPtr = (struct TextFont *) OpenDiskFont(&WormWars8)))
  354. {    /* loaded WormWars.font
  355.  
  356.         It would be possible to pass SA_Interleaved on any OS version,
  357.     provided that it was ignored by 2.04-2.1. */
  358.  
  359.     if (IntuitionBase->LibNode.lib_Version >= 39) /* if we're running on OS3.0+ */
  360.     {    ScreenPtr = (struct Screen *) OpenScreenTags
  361.         (    NULL,
  362.             SA_Width,            640,
  363.             SA_Height,            256,
  364.             SA_Depth,            DEPTH,
  365.             SA_DisplayID,       HIRES_KEY | PAL_MONITOR_ID,
  366.             SA_Title,            TITLEBAR,
  367.             SA_Colors,            Colours,
  368.             SA_Font,            &WormWars8,
  369.             SA_Pens,            Pens,
  370.             SA_Interleaved,        TRUE,
  371.             TAG_DONE
  372.         );
  373.     } else
  374.     {    ScreenPtr = (struct Screen *) OpenScreenTags
  375.         (    NULL,
  376.             SA_Width,            640,
  377.             SA_Height,            256,
  378.             SA_Depth,            DEPTH,
  379.             SA_DisplayID,        HIRES_KEY | PAL_MONITOR_ID,
  380.             SA_Title,            TITLEBAR,
  381.             SA_Colors,            Colours,
  382.             SA_Font,            &WormWars8,
  383.             SA_Pens,            Pens,
  384.             TAG_DONE
  385.         );
  386.     }
  387.     if (!ScreenPtr)
  388.     {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open screen!\0", 24);
  389.         cleanexit(EXIT_FAILURE);
  390. }    }
  391. else
  392. {    if (!error)
  393.         error = 2;
  394.  
  395.     if (IntuitionBase->LibNode.lib_Version >= 39) /* if we're running on OS3.0+ */
  396.     {    ScreenPtr = (struct Screen *) OpenScreenTags
  397.         (    NULL,
  398.             SA_Width,            640,
  399.             SA_Height,            256,
  400.             SA_Depth,            DEPTH,
  401.             SA_DisplayID,        HIRES_KEY | PAL_MONITOR_ID,
  402.             SA_Title,            TITLEBAR,
  403.                 SA_Colors,            Colours,
  404.                 SA_Font,            &Topaz8,
  405.             SA_Pens,            Pens,
  406.             SA_Interleaved,            TRUE,
  407.             TAG_DONE
  408.         );
  409.     } else
  410.     {    ScreenPtr = (struct Screen *) OpenScreenTags
  411.         (    NULL,
  412.             SA_Width,            640,
  413.             SA_Height,            256,
  414.             SA_Depth,            DEPTH,
  415.             SA_DisplayID,        HIRES_KEY | PAL_MONITOR_ID,
  416.             SA_Title,            TITLEBAR,
  417.                 SA_Colors,            Colours,
  418.                 SA_Font,            &Topaz8,
  419.             SA_Pens,            Pens,
  420.             TAG_DONE
  421.         );
  422.     }
  423.     if (!ScreenPtr)
  424.     {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open screen nor font!\0", 24);
  425.         cleanexit(EXIT_FAILURE);
  426. }    }
  427.  
  428. /* For some reason, we lose 2 memory chunks: 264 bytes and 10 bytes. This
  429. seems perhaps to not be our fault. */
  430.  
  431. /* GadTools */
  432.  
  433. if (!(CycleGadget.ng_VisualInfo = StringGadget.ng_VisualInfo = CheckboxGadget.ng_VisualInfo = VisualInfoPtr = (APTR) GetVisualInfo(ScreenPtr, TAG_DONE)))
  434. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't get GadTools visual info!\0", 24);
  435.     cleanexit(EXIT_FAILURE);
  436. }
  437. if (!(MenuPtr = (struct Menu *) CreateMenus(NewMenu, TAG_DONE)))
  438. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create menus!\0", 24);
  439.     cleanexit(EXIT_FAILURE);
  440. }
  441. if (!(LayoutMenus(MenuPtr, VisualInfoPtr, TAG_DONE)))
  442. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't lay out menus!\0", 24);
  443.     cleanexit(EXIT_FAILURE);
  444. }
  445. if (!(PrevGadgetPtr = (struct Gadget *) CreateContext(&GListPtr)))
  446. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create GadTools context!\0", 24);
  447.     cleanexit(EXIT_FAILURE);
  448. }
  449. for (player = 0; player <= 3; player++)
  450. {    CycleGadget.ng_TopEdge = 184 + (player * (FONTX + 8));
  451.     CycleGadget.ng_GadgetText = CycleText[player];
  452.     CycleGadgetPtr[player] = PrevGadgetPtr = (struct Gadget *) CreateGadget
  453.     (    CYCLE_KIND,
  454.         PrevGadgetPtr,
  455.         &CycleGadget,
  456.         GTCY_Labels, CycleOptions[player],
  457.         GTCY_Active, worm[player].control,
  458.         GT_Underscore, '_',
  459.         GA_Disabled, TRUE,
  460.         TAG_DONE
  461.     );
  462. }
  463. CheckboxGadgetPtr = PrevGadgetPtr = (struct Gadget *) CreateGadget
  464. (    CHECKBOX_KIND,
  465.     PrevGadgetPtr,
  466.     &CheckboxGadget,
  467.     GTCB_Checked, iso,
  468.     GT_Underscore, '_',
  469.     GA_Disabled, TRUE,
  470.     TAG_DONE
  471. );
  472.  
  473. /* main window */
  474.  
  475. if (!(MainWindowPtr = (struct Window *) OpenWindowTags(NULL,
  476.     WA_Top,                11,
  477.     WA_Width,            SCREENXPIXEL,
  478.     WA_Height,            SCREENYPIXEL,
  479.     WA_IDCMP,           IDCMP_RAWKEY | IDCMP_MOUSEBUTTONS | IDCMP_CLOSEWINDOW | IDCMP_ACTIVEWINDOW | IDCMP_MENUPICK | IDCMP_MENUVERIFY | CYCLEIDCMP | STRINGIDCMP | CHECKBOXIDCMP | IDCMP_REFRESHWINDOW | IDCMP_INTUITICKS,
  480.     WA_Gadgets,            GListPtr,
  481.     WA_CustomScreen,    ScreenPtr,
  482.     WA_Borderless,        TRUE,
  483.     WA_Activate,        TRUE,
  484.     WA_SmartRefresh,    TRUE,
  485.     WA_RptQueue,        16,
  486.     TAG_DONE)))
  487.     {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't open main window!\0", 24);
  488.         cleanexit(EXIT_FAILURE);
  489.     }
  490.  
  491. /* redirection of AmigaDOS system requesters */
  492.     
  493. OldWindowPtr = ProcessPtr->pr_WindowPtr;
  494. ProcessPtr->pr_WindowPtr = (APTR) MainWindowPtr;
  495.  
  496. if (!(ASLRqPtr = AllocAslRequestTags(ASL_FileRequest, ASL_Pattern, PATTERN, ASL_Window, MainWindowPtr, TAG_DONE)))
  497. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create ASL request!\0", 24);
  498.     cleanexit(EXIT_FAILURE);
  499. }
  500.  
  501. /* String gadgets: first the window is opened with the cycle and
  502. checkbox gadgets.
  503.     It is necessary not to display the string gadgets yet, so the
  504. gadgets are then created and added to the gadget list. You will note
  505. there is no command given to render them as yet. When the attributes
  506. are modified at highscore time, the applicable gadget is refreshed
  507. then. */
  508.  
  509. for (which = 0; which <= HISCORES; which++)
  510. {    StringGadget.ng_TopEdge = 104 + (which * HISCOREDISTANCE);
  511.     StringGadgetPtr[which] = PrevGadgetPtr = (struct Gadget *) CreateGadget(STRING_KIND, PrevGadgetPtr, &StringGadget, GTST_MaxChars, NAMELENGTH, STRINGA_ReplaceMode, TRUE, GA_Disabled, TRUE, TAG_DONE);
  512. }
  513. if (!PrevGadgetPtr)
  514. {    DisplayAlert(AT_Recovery, "\0\20\20Worm Wars: Can't create GadTools gadgets!\0", 24);
  515.     cleanexit(EXIT_FAILURE);
  516. }
  517.  
  518. if (!icons)
  519.         NewMenu[CREATEICONS].nm_Flags &= ~CHECKED;
  520.  
  521. if (error == 1)
  522. {    say("Can't open diskfont.library!", RED);
  523.     anykey(TRUE);
  524. } else if (error == 2)
  525. {    say("Can't open WormWars.font!", RED);
  526.     anykey(TRUE);
  527. }
  528.  
  529. if (!(JoyPortPtr = (struct MsgPort *) CreateMsgPort()))
  530. {    say("Can't create joystick message port!", BLUE);
  531.     anykey(TRUE);
  532. } else if (!(JoyRqPtr = (struct IOStdReq *) CreateIORequest(JoyPortPtr, sizeof(struct IOStdReq))))
  533. {    say("Can't create joystick I/O request!", BLUE);
  534.     anykey(TRUE);
  535. } else if (JoyClosed = OpenDevice("gameport.device", 1, JoyRqPtr, 0))
  536. {    say("Can't open gameport.device!", BLUE);
  537.     anykey(TRUE);
  538. } else
  539. {    Forbid();
  540.     JoyRqPtr->io_Command        = GPD_ASKCTYPE;
  541.     JoyRqPtr->io_Length            = 1;
  542.     JoyRqPtr->io_Flags            = IOF_QUICK;
  543.     JoyRqPtr->io_Data            = (APTR) &Controller;
  544.     DoIO(JoyRqPtr);
  545.     if (Controller == GPCT_NOCONTROLLER)
  546.     {    Controller                = GPCT_ABSJOYSTICK;
  547.         JoyRqPtr->io_Command    = GPD_SETCTYPE;
  548.         JoyRqPtr->io_Length     = 1;
  549.         JoyRqPtr->io_Data        = (APTR) &Controller;
  550.         DoIO(JoyRqPtr);
  551.         success = TRUE;
  552.     }
  553.     Permit();
  554.     /* Note that say(), anykey() calls must be outside the
  555.     Forbid()/Permit() pair. */
  556.     if (success)
  557.     {    JoyRqPtr->io_Command    = GPD_SETTRIGGER;
  558.         JoyRqPtr->io_Data        = (APTR) &Trigger;
  559.         JoyRqPtr->io_Length        = sizeof(struct GamePortTrigger);
  560.         DoIO(JoyRqPtr);
  561.         sendreadrequest();
  562.         joy = TRUE;
  563.     } else
  564.     {    say("Gameport already in use!", BLUE);
  565.         anykey(TRUE);
  566. }    }
  567.  
  568. /* By default, preload music and sound effects at startup.
  569. musicable and fxable values are:
  570.  
  571. 0: tried and failed
  572. 1: tried and succeeded
  573. 2: untried, will load at startup
  574. 3: untried, will load when needed */
  575.  
  576. if (musicable == 2)
  577.     loadthemusic();
  578. if (fxable == 2)
  579.     loadthefx();
  580.  
  581. if (fxable == 1)
  582.     toggle(F);
  583. else if (musicable == 1)
  584.     toggle(M);
  585.  
  586. strcpy(saystring, "Loading ");
  587. strcat(saystring, pathname);
  588. strcat(saystring, "...");
  589. say(saystring, WHITE);
  590. if (loadfields(pathname))
  591. {    strcpy(saystring, "Can't open ");
  592.     strcat(saystring, pathname);
  593.     strcat(saystring, "!");
  594.     say(saystring, RED);
  595.         newfields();
  596.     anykey(TRUE);
  597. }
  598.  
  599. while (1)
  600. {    titlescreen();
  601.  
  602.     /* MAIN GAME LOOP ------------------------------------------------- */
  603.  
  604.     while (a == PLAYGAME)
  605.         {       r++;
  606.                 oldsecondsleft = secondsleft;
  607.                 GetSysTime(CurrentValPtr);
  608.                 SubTime(CurrentValPtr, StartValPtr);
  609.                 secondsleft = secondsperlevel - CurrentValPtr->tv_secs;
  610.                 if (secondsleft != oldsecondsleft)
  611.                     timeloop();
  612.         TimerRqPtr->tr_node.io_Command    = TR_ADDREQUEST;
  613.                 TimerRqPtr->tr_time.tv_secs     = 0;
  614.         TimerRqPtr->tr_time.tv_micro    = delay;
  615.         SendIO(TimerRqPtr);
  616.         gameloop();
  617.         if (CheckIO(TimerRqPtr))
  618.             draw(CLOCKICON, ICONY, CLOCK);
  619.                 else draw(CLOCKICON, ICONY, BLACKENED);
  620.         WaitIO(TimerRqPtr);
  621.     }
  622.     say("Title Screen", WHITE);
  623. }
  624. }
  625.  
  626. /* SUPPORT FUNCTIONS ----------------------------------------------------- */
  627.  
  628. /* NAME     anykey -- wait for a user press
  629. SYNOPSIS    anykey(ABOOL);
  630. FUNCTION    Waits for a user response. Optional automatic timeout.
  631. INPUTS      timeout - timeout?
  632. RESULTS     FALSE if user presses Escape, TRUE otherwise.
  633. FILE        system.c */
  634.  
  635. ABOOL anykey(ABOOL timeout)
  636. {    ABOOL                    done        = FALSE;
  637.     SBYTE                    count        = 0;
  638.     UWORD                    code, qual;
  639.     ULONG                    class;
  640.     struct IntuiMessage*    MsgPtr;
  641.  
  642.     clearkybd();
  643.     Forbid();
  644.     MainWindowPtr->Flags |= WFLG_RMBTRAP;
  645.     Permit();
  646.     
  647.     while (!done)
  648.     {    if (joy && GetMsg(JoyPortPtr))
  649.         {    if (GameEvent.ie_Code == IECODE_LBUTTON)
  650.                 done = TRUE;
  651.             sendreadrequest();
  652.         }
  653.         if (joy)
  654.         {    Wait((1L << MainWindowPtr->UserPort->mp_SigBit) | (1L << JoyPortPtr->mp_SigBit));
  655.             while (GetMsg(JoyPortPtr))
  656.             {    if (GameEvent.ie_Code == IECODE_LBUTTON)
  657.                     done = TRUE;
  658.                 sendreadrequest();
  659.         }    }
  660.         else Wait(1L << MainWindowPtr->UserPort->mp_SigBit);
  661.         while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
  662.         {    class = MsgPtr->Class;
  663.             code  = MsgPtr->Code;
  664.             qual  = MsgPtr->Qualifier;
  665.             GT_ReplyIMsg(MsgPtr);
  666.             switch(class)
  667.             {
  668.             case IDCMP_RAWKEY:
  669.                             if ((!(qual & IEQUALIFIER_REPEAT)) && code < KEYUP && (code < FIRSTQUALIFIER || code > LASTQUALIFIER))
  670.                             {   done = TRUE;
  671.                                 if (code == M)
  672.                                     toggle(M);
  673.                                 else if (code == F)
  674.                                     toggle(F);
  675.                                 else if (code == ESCAPE)
  676.                                 {   if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  677.                                         if (verify())
  678.                                             cleanexit(EXIT_SUCCESS);
  679.                                     else
  680.                                     {   Forbid();
  681.                                         MainWindowPtr->Flags &= ~WFLG_RMBTRAP;
  682.                                         Permit();
  683.                                         return FALSE;
  684.                             }   }   }
  685.                         break;
  686.             case IDCMP_CLOSEWINDOW:
  687.                 cleanexit(EXIT_SUCCESS);
  688.                 break;
  689.             case IDCMP_ACTIVEWINDOW:
  690.                 ignore = TRUE;
  691.                 break;
  692.             case IDCMP_MOUSEBUTTONS:
  693.                 if ((code == SELECTDOWN || code == MENUDOWN) && !(qual & IEQUALIFIER_REPEAT))
  694.                     if (ignore)
  695.                         ignore = FALSE;
  696.                     else done = TRUE;
  697.                 break;
  698.             case IDCMP_INTUITICKS:
  699.                 if (timeout && ++count > PATIENCE)
  700.                     done = TRUE;
  701.                 break;
  702.             default:
  703.                 break;
  704.     }    }    }
  705.  
  706.     Forbid();
  707.     MainWindowPtr->Flags &= ~WFLG_RMBTRAP;
  708.     Permit();
  709.     return TRUE;
  710. }
  711.  
  712. void celebrate(void)
  713. {    ABOOL                    done = FALSE;
  714.     ULONG                    class;
  715.     UWORD                    code, qual;
  716.     struct IntuiMessage*    MsgPtr;
  717.     UBYTE                   player;
  718.  
  719.     for (player = 0; player <= 3; player++)
  720.         if (worm[player].control != NONE && worm[player].score >= worm[player].hiscore)
  721.              worm[player].hiscore = worm[player].score;
  722.     waitasec();
  723.     clearkybd();
  724.     while (!done)
  725.     {    while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
  726.         {    class = MsgPtr->Class;
  727.             code  = MsgPtr->Code;
  728.             qual  = MsgPtr->Qualifier;
  729.             GT_ReplyIMsg(MsgPtr);
  730.             switch (class)
  731.             {
  732.             case IDCMP_RAWKEY:
  733.                 if (code == ESCAPE)
  734.                 {    if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  735.                     {    if (verify())
  736.                             cleanexit(EXIT_SUCCESS);
  737.                     } else
  738.                         done = TRUE;
  739.                 }
  740.                 else if (code == RETURN || code == ENTER || code == SPACEBAR)
  741.                     done = TRUE;
  742.                 else if (code == M)
  743.                     toggle(M);
  744.                 else if (code == F)
  745.                     toggle(F);
  746.                 break;
  747.             case IDCMP_MOUSEBUTTONS:
  748.                 if (code == SELECTDOWN && !(qual & IEQUALIFIER_REPEAT))
  749.                     if (ignore)
  750.                         ignore = FALSE;
  751.                     else done = TRUE;
  752.                 break;
  753.             case IDCMP_ACTIVEWINDOW:
  754.                 ignore = TRUE;
  755.                 break;
  756.             case IDCMP_CLOSEWINDOW:
  757.                 cleanexit(EXIT_SUCCESS);
  758.                 break;
  759.             default:
  760.                 break;
  761.         }    }
  762.         if (joy && GetMsg(JoyPortPtr))
  763.         {    if (GameEvent.ie_Code == IECODE_LBUTTON)
  764.                 done = TRUE;
  765.             sendreadrequest();
  766.         }
  767.         SetRGB4(&ScreenPtr->ViewPort, 17, rand() % 16, rand() % 16, rand() % 16);
  768.         draw(rand() % (FIELDX + 1), rand() % (FIELDY + 1), rand() % LASTOBJECT);
  769.     }
  770.     SetRGB4(&ScreenPtr->ViewPort, 17, 14, 4, 4);
  771.     a = GAMEOVER;
  772. }
  773.  
  774. AGLOBAL void cleanexit(SLONG rc)
  775. {   SBYTE i;
  776.     
  777. if (TimerRqPtr && (!CheckIO(TimerRqPtr)))
  778.                     {    AbortIO(TimerRqPtr);
  779.                         WaitIO(TimerRqPtr);                                }
  780.                         freefx();
  781.                         for (i = 0; i <= SAMPLES; i++)
  782.                             if (samp[i].base)
  783.                                 FreeMem(samp[i].base, samp[i].size);
  784. if (mode == MUSIC)        StopPlayer();
  785. if (SongPtr)            UnLoadModule(SongPtr);
  786. if (MEDPlayerBase)    {    FreePlayer();
  787.                         CloseLibrary(MEDPlayerBase);                    }
  788.  
  789. if (joy)            {    AbortIO(JoyRqPtr);
  790.                         WaitIO(JoyRqPtr);                                }
  791. if (Controller != GPCT_NOCONTROLLER)
  792.                     {    Forbid();
  793.                         Controller                = GPCT_NOCONTROLLER;
  794.                         JoyRqPtr->io_Command    = GPD_SETCTYPE;
  795.                         JoyRqPtr->io_Length        = 1;
  796.                         JoyRqPtr->io_Data        = (APTR) &Controller;
  797.                         DoIO(JoyRqPtr);
  798.                         Permit();                                        }
  799. if (!JoyClosed)            CloseDevice(JoyRqPtr);
  800. if (JoyRqPtr)            DeleteIORequest(JoyRqPtr);
  801. if (JoyPortPtr)            DeleteMsgPort(JoyPortPtr);
  802.  
  803. if (ASLRqPtr)            FreeAslRequest(ASLRqPtr);
  804. if (OldWindowPtr)        ProcessPtr->pr_WindowPtr = OldWindowPtr;
  805. if (MainWindowPtr)    {    clearkybd();
  806.                         ClearMenuStrip(MainWindowPtr);
  807.                         CloseWindow(MainWindowPtr);                        }
  808. if (GListPtr)            FreeGadgets(GListPtr);
  809. if (MenuPtr)            FreeMenus(MenuPtr);
  810. if (VisualInfoPtr)        FreeVisualInfo(VisualInfoPtr);
  811. if (ScreenPtr)            CloseScreen(ScreenPtr);
  812. if (FontPtr)            CloseFont(FontPtr);
  813. if (!TimerClosed)        CloseDevice(TimerRqPtr);
  814. if (TimerRqPtr)            DeleteIORequest(TimerRqPtr);
  815. if (TimerPortPtr)        DeleteMsgPort(TimerPortPtr);
  816. if (PausedValPtr)        FreeMem(PausedValPtr, sizeof(struct timeval));
  817. if (CurrentValPtr)        FreeMem(CurrentValPtr, sizeof(struct timeval));
  818. if (StartValPtr)        FreeMem(StartValPtr, sizeof(struct timeval));
  819. if (DiskFontBase)        CloseLibrary(DiskFontBase);
  820. if (UtilityBase)        CloseLibrary(UtilityBase);
  821. if (ASLBase)            CloseLibrary(ASLBase);
  822. if (GadToolsBase)        CloseLibrary(GadToolsBase);
  823. if (GfxBase)            CloseLibrary(GfxBase);
  824. if (IconBase)            CloseLibrary(IconBase);
  825. if (IntuitionBase)    {    OpenWorkBench();
  826.                         CloseLibrary(IntuitionBase);                    }
  827.                         SetTaskPri((struct Task *) ProcessPtr, OldPri);
  828. if (ArgsPtr)            FreeArgs(ArgsPtr);
  829.                         exit(rc);                /* End of program. */
  830. }
  831.  
  832. void clearjoystick(void)
  833. {    if (joy)
  834.         while (GetMsg(JoyPortPtr))
  835.             sendreadrequest();
  836. }
  837.  
  838. void clearkybd(void)
  839. {    struct IntuiMessage* MsgPtr;
  840.  
  841.     while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
  842.         GT_ReplyIMsg(MsgPtr);
  843. }
  844.  
  845. void draw(SBYTE x, SBYTE y, SBYTE image)
  846. {    SWORD pixx;
  847.     
  848.     /* Isometric methodology:
  849.     
  850.     read the colour of the pixel, then set the colour in the image
  851.     to the same value.
  852.  
  853.     So if, for the top left pixel, we read colour 10 (= $A or %1010),
  854.     we have to clear the relevant bits in plane 0 and 2, and set them
  855.     in planes 1 and 3.
  856.  
  857.     plane 0 (least significant bit)
  858.         1234567890123456 pixels for top row (y = 0)
  859.         1234567890123456 pixels for next row (y = 1)
  860.         : : :
  861.     plane 1
  862.         : : :
  863.  
  864.      01234567890
  865.     0..#########
  866.     1..#########
  867.     2.#########.
  868.     3.#########.
  869.     4#########..
  870.     5#########..
  871.  
  872.     Image is effectively 9*6, but requires an 11*6 bitmap.
  873.  
  874.      31
  875.      268421
  876.      731000521
  877.      689942152631
  878.      8426842684268421
  879.      **.......**..... */
  880.  
  881.     if (a == PLAYGAME && iso)
  882.     {    IsoImage.ImageData = IsoImageData[image];
  883.         pixx = (x * ISOSQUAREX) + 20 + ((FIELDY - y) * 3);
  884.         pixy = (y * ISOSQUAREY) + STARTYPIXEL;
  885.         preserve(pixx,      0, image, 32768);
  886.         preserve(pixx,      1, image, 32768);
  887.         preserve(pixx,      2, image, 32768);
  888.         preserve(pixx,      3, image, 32768);
  889.         preserve(pixx +  1, 0, image, 16384);
  890.         preserve(pixx +  1, 1, image, 16384);
  891.         preserve(pixx +  9, 4, image,    64);
  892.         preserve(pixx +  9, 5, image,    64);
  893.         preserve(pixx + 10, 2, image,    32);
  894.         preserve(pixx + 10, 3, image,    32);
  895.         preserve(pixx + 10, 4, image,    32);
  896.         preserve(pixx + 10, 5, image,    32);
  897.         DrawImage
  898.         (    MainWindowPtr->RPort,
  899.             &IsoImage,
  900.             pixx,
  901.             pixy
  902.         );
  903.     } else
  904.     {    /* blit square */
  905.  
  906.         Image.ImageData = ImageData[image];
  907.         DrawImage
  908.         (    MainWindowPtr->RPort,
  909.             &Image,
  910.             STARTXPIXEL + (SQUAREX * x),
  911.             STARTYPIXEL + (SQUAREY * y)
  912.         );
  913. }    }
  914.  
  915. MODULE void preserve(SWORD x, SBYTE row, SBYTE image, UWORD amount)
  916. {    LONG colour;
  917.     
  918.     /* x = image top-left corner coordinate on destination screen.
  919.     row = y-row of the image.
  920.     image = image number
  921.     amount = value of the bit to be set/cleared. */
  922.  
  923.     colour = ReadPixel
  924.     (    MainWindowPtr->RPort,
  925.         x,
  926.         pixy + row
  927.     );
  928.     if (colour & 8)
  929.         IsoImageData[image][row + 18] |= amount;
  930.     else IsoImageData[image][row + 18] &= ~amount;
  931.     if (colour & 4)
  932.         IsoImageData[image][row + 12] |= amount;
  933.     else IsoImageData[image][row + 12] &= ~amount;
  934.     if (colour & 2)
  935.         IsoImageData[image][row + 6] |= amount;
  936.     else IsoImageData[image][row + 6] &= ~amount;
  937.     if (colour & 1)
  938.         IsoImageData[image][row] |= amount;
  939.     else IsoImageData[image][row] &= ~amount;
  940. }
  941.  
  942. void effect(SBYTE index)
  943. {           SBYTE    i;
  944.             SBYTE    ok                = -1;
  945.             ULONG   oldestreceipt    = (ULONG) -1L;
  946.     PERSIST    ULONG   nextreceipt            = 1L;
  947.  
  948.     /* oldestreceipt = temporary variable for ascertaining oldest
  949.     sound still playing.
  950.     nextreceipt = next unused receipt number (monotonically incrementing). */
  951.  
  952.     if (mode == FX)
  953.     {    for (i = 0; i <= 3; i++)
  954.         {    /* decide on a channel */
  955.  
  956.             if (ok == -1)
  957.             {    if (!eversent[i])
  958.                     ok = i;
  959.                 else if (CheckIO(AudioRqPtr[i]))
  960.                 {    WaitIO(AudioRqPtr[i]);
  961.                     ok = i;
  962.         }    }    }
  963.         if (ok == -1)
  964.         {   for (i = 0; i <= 3; i++)
  965.                 if (receipter[i] < oldestreceipt)
  966.                 {   ok = i;
  967.                     oldestreceipt = receipter[i];
  968.                 }
  969.             AbortIO(AudioRqPtr[ok]);
  970.             WaitIO(AudioRqPtr[ok]);
  971.         }
  972.         eversent[ok] = TRUE;
  973.         AudioRqPtr[ok]->ioa_Cycles              = 1;
  974.         AudioRqPtr[ok]->ioa_Request.io_Command  = CMD_WRITE;
  975.         AudioRqPtr[ok]->ioa_Request.io_Flags    = ADIOF_PERVOL;
  976.         AudioRqPtr[ok]->ioa_Request.io_Unit     = (1 << ok);
  977.         AudioRqPtr[ok]->ioa_Volume              = samp[index].volume;
  978.         AudioRqPtr[ok]->ioa_Period              = (UWORD) samp[index].speed;
  979.         AudioRqPtr[ok]->ioa_Request.io_Message.mn_ReplyPort
  980.                                                 = AudioPortPtr[ok];
  981.         AudioRqPtr[ok]->ioa_Data                = (UBYTE *) samp[index].base;
  982.         AudioRqPtr[ok]->ioa_Length              = samp[index].length[samp[index].bank];
  983.         BeginIO(AudioRqPtr[ok]);
  984.         receipter[ok] = nextreceipt;
  985. }   }
  986.  
  987. void fieldedit(void)
  988. {        UBYTE                    oldbrush = ANYTHING, stamp;
  989.         SBYTE                    deltax = 0, deltay = 0, lastx, lasty, pointerx, pointery, which, x, y;
  990.         UWORD                    code, qual;
  991.         ULONG                    class;
  992.         struct IntuiMessage*    MsgPtr;
  993.         ABOOL                    leftdown = FALSE, rightdown = FALSE, timer = FALSE;
  994.         struct MenuItem*        ItemPtr;
  995. PERSIST    SBYTE                    clipboard[FIELDX + 1][FIELDY + 1];
  996. PERSIST    ABOOL                    clipboarded = FALSE;
  997.  
  998. say("Field Editor", WHITE);
  999. setpointer(brush);
  1000. if (level > levels)
  1001.     level = levels;
  1002. OnMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, NOITEM, NOSUB));
  1003. if (!clipboarded)
  1004.     OffMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, IN_PASTE, NOSUB));
  1005.  
  1006. /* draw pseudo-gadgets */
  1007.  
  1008. clearscreen();
  1009. for (which = 0; which <= 8; which++)
  1010.     DrawBevelBox(MainWindowPtr->RPort, STARTXPIXEL - 5 - (SQUAREX * 3), 40 + STARTYPIXEL + (which * SQUAREY * 3), SQUAREX + 9, SQUAREY + 4, GT_VisualInfo, VisualInfoPtr);
  1011. SetAPen(MainWindowPtr->RPort, WHITE);
  1012. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + (  GOLDGADGET * SQUAREY));
  1013. Text(MainWindowPtr->RPort, "F1:", 3);
  1014. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + (SILVERGADGET * SQUAREY));
  1015. Text(MainWindowPtr->RPort, "F2:", 3);
  1016. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + ( EMPTYGADGET * SQUAREY));
  1017. Text(MainWindowPtr->RPort, "F3:", 3);
  1018. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + (  WOODGADGET * SQUAREY));
  1019. Text(MainWindowPtr->RPort, "F4:", 3);
  1020. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + ( STONEGADGET * SQUAREY));
  1021. Text(MainWindowPtr->RPort, "F5:", 3);
  1022. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + ( METALGADGET * SQUAREY));
  1023. Text(MainWindowPtr->RPort, "F6:", 3);
  1024. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + (   ONEGADGET * SQUAREY));
  1025. Text(MainWindowPtr->RPort, "F7:", 3);
  1026. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + (   TWOGADGET * SQUAREY));
  1027. Text(MainWindowPtr->RPort, "F8:", 3);
  1028. Move(MainWindowPtr->RPort, STARTXPIXEL - (FONTX * 8), STARTYPIXEL + 5 + ( STARTGADGET * SQUAREY));
  1029. Text(MainWindowPtr->RPort, "F9:", 3);
  1030. draw(GADGETX,   GOLDGADGET,   GOLD);
  1031. draw(GADGETX, SILVERGADGET, SILVER);
  1032. draw(GADGETX,  EMPTYGADGET,  EMPTY);
  1033. draw(GADGETX,   WOODGADGET,   WOOD);
  1034. draw(GADGETX,  STONEGADGET,  STONE);
  1035. draw(GADGETX,  METALGADGET,  METAL);
  1036. draw(GADGETX,    ONEGADGET,    ONE);
  1037. draw(GADGETX,    TWOGADGET,    TWO);
  1038. draw(GADGETX,  STARTGADGET,  START);
  1039. SetAPen(MainWindowPtr->RPort, BLACK);
  1040. RectFill
  1041. (    MainWindowPtr->RPort,
  1042.     STARTXPIXEL - SQUAREX - 1,
  1043.     UNDERLINEOFFSET - 1,
  1044.     STARTXPIXEL - SQUAREX + 3,
  1045.     UNDERLINEOFFSET + 4 + (SQUAREY * 25)
  1046. );
  1047. underline(brush);
  1048.  
  1049. turborender();
  1050. saylevel(WHITE);
  1051. clearkybd();
  1052. x = lastx = startx[level];
  1053. y = lasty = starty[level];
  1054.     
  1055. while (a == FIELDEDIT)
  1056. {    stamp = NOSQUARE;
  1057.  
  1058.     if (MsgPtr = (struct IntuiMessage *) GetMsg(MainWindowPtr->UserPort))
  1059.     {    class = MsgPtr->Class;
  1060.         code  = MsgPtr->Code;
  1061.         qual  = MsgPtr->Qualifier;
  1062.         if (class == IDCMP_MENUVERIFY && MsgPtr->MouseX >= STARTXPIXEL && MsgPtr->MouseX <= ENDXPIXEL && MsgPtr->MouseY >= STARTYPIXEL && MsgPtr->MouseY <= ENDYPIXEL)
  1063.         {    MsgPtr->Code = MENUCANCEL;
  1064.             oldbrush = brush;
  1065.             brush = EMPTY;
  1066.             rightdown = TRUE;
  1067.         }
  1068.         ReplyMsg(MsgPtr);
  1069.         switch (class)
  1070.         {
  1071.         case IDCMP_MENUPICK:
  1072.             while (code != MENUNULL)
  1073.             {    ItemPtr = ItemAddress(MenuPtr, code);
  1074.                 switch (MENUNUM(code))
  1075.                 {
  1076.                 case MN_PROJECT:
  1077.                     switch (ITEMNUM(code))
  1078.                     {
  1079.                     case IN_NEW:
  1080.                         effect(FXFILENEW);
  1081.                         newfields();
  1082.                         say("New done.", WHITE);
  1083.                     break;
  1084.                     case IN_OPEN:
  1085.                         effect(FXFILEOPEN);
  1086.                         fileopen(FALSE);
  1087.                     break;
  1088.                     case IN_REVERT:
  1089.                         fileopen(TRUE);
  1090.                     break;
  1091.                     case IN_SAVE:
  1092.                         effect(FXFILESAVE);
  1093.                         if (modified)
  1094.                         {    clearhiscores();
  1095.                             modified = FALSE;
  1096.                         }
  1097.                         filesaveas(FALSE);
  1098.                         break;
  1099.                     case IN_SAVEAS:
  1100.                         effect(FXFILESAVEAS);
  1101.                         if (modified)
  1102.                         {    clearhiscores();
  1103.                             modified = FALSE;
  1104.                         }
  1105.                         filesaveas(TRUE);
  1106.                         break;
  1107.                     case IN_QUIT:
  1108.                         if (verify())
  1109.                             cleanexit(EXIT_SUCCESS);
  1110.                         break;
  1111.                     default:
  1112.                         break;
  1113.                     }
  1114.                     break;
  1115.                 case MN_EDIT:
  1116.                     switch (ITEMNUM(code))
  1117.                     {
  1118.                     case IN_CUT:
  1119.                         effect(FXEDITCUT);
  1120.                         for (x = 0; x <= FIELDX; x++)
  1121.                             for (y = 0; y <= FIELDY; y++)
  1122.                                 clipboard[x][y] = board[level][x][y];
  1123.                         leveldelete();
  1124.                         clipboarded = TRUE;
  1125.                         modified = TRUE;
  1126.                         OnMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, IN_PASTE, NOSUB));
  1127.                     break;
  1128.                     case IN_COPY:
  1129.                         effect(FXEDITCOPY);
  1130.                         for (x = 0; x <= FIELDX; x++)
  1131.                             for (y = 0; y <= FIELDY; y++)
  1132.                                 clipboard[x][y] = board[level][x][y];
  1133.                         clipboarded = TRUE;
  1134.                         OnMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, IN_PASTE, NOSUB));
  1135.                     break;
  1136.                     case IN_PASTE:
  1137.                         effect(FXEDITPASTE);
  1138.                         for (x = 0; x <= FIELDX; x++)
  1139.                             for (y = 0; y <= FIELDY; y++)
  1140.                                 board[level][x][y] = clipboard[x][y];
  1141.                         turborender();
  1142.                         modified = TRUE;
  1143.                     break;
  1144.                     case IN_ERASE:
  1145.                         levelerase();
  1146.                     break;
  1147.                     case IN_INSERT:
  1148.                         levelinsert();
  1149.                     break;
  1150.                     case IN_DELETE:
  1151.                         effect(FXLEVELDELETE);
  1152.                         leveldelete();
  1153.                     break;
  1154.                     case IN_APPEND:
  1155.                         levelappend();
  1156.                     break;
  1157.                     default:
  1158.                     break;
  1159.                     }
  1160.                 break;
  1161.                 case MN_SETTINGS:
  1162.                     switch(ITEMNUM(code))
  1163.                     {
  1164.                     case IN_CREATEICONS:
  1165.                         if (ItemPtr->Flags & CHECKED)
  1166.                             icons = TRUE;
  1167.                         else icons = FALSE;
  1168.                     break;
  1169.                     default:
  1170.                     break;
  1171.                     }
  1172.                 break;
  1173.                 case MN_HELP:
  1174.                     switch(ITEMNUM(code))
  1175.                     {
  1176.                     case IN_CREATURES:
  1177.                         help(ORB);
  1178.                     break;
  1179.                     case IN_OBJECTS:
  1180.                         help(AFFIXER);
  1181.                     break;
  1182.                     case IN_MANUAL:
  1183.                         helpmanual();
  1184.                     break;
  1185.                     case IN_ABOUT:
  1186.                         helpabout();
  1187.                     break;
  1188.                     default:
  1189.                     break;
  1190.                     }
  1191.                 break;
  1192.                 default:
  1193.                 break;
  1194.                 }
  1195.                 code = ItemPtr->NextSelect;
  1196.             }
  1197.             break;
  1198.             case IDCMP_RAWKEY:
  1199.                 lastx = x;
  1200.                 lasty = y;
  1201.             switch(code)
  1202.             {
  1203.             case DELETE:
  1204.                 if (!(qual & IEQUALIFIER_REPEAT))
  1205.                 {    effect(FXCLICK);
  1206.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1207.                         level = 1;
  1208.                     else if (--level < 0)
  1209.                         level = levels;
  1210.                     saylevel(WHITE);
  1211.                     turborender();
  1212.                 }
  1213.                 break;
  1214.             case HELP:
  1215.                 if (!(qual & IEQUALIFIER_REPEAT))
  1216.                 {    effect(FXCLICK);
  1217.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1218.                         level = levels;
  1219.                     else if (++level > levels)
  1220.                         level = 0;
  1221.                     saylevel(WHITE);
  1222.                     turborender();
  1223.                 }
  1224.                 break;
  1225.             case M:
  1226.                 if (!(qual & IEQUALIFIER_REPEAT))
  1227.                     toggle(M);
  1228.                 break;
  1229.             case F:
  1230.                 if (!(qual & IEQUALIFIER_REPEAT))
  1231.                     toggle(F);
  1232.                 break;
  1233.             case ESCAPE:
  1234.                 if (!(qual & IEQUALIFIER_REPEAT))
  1235.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1236.                     {    if (verify())
  1237.                         cleanexit(EXIT_SUCCESS);
  1238.                     } else a = GAMEOVER;
  1239.             break;
  1240.             case SPACEBAR:
  1241.             case RETURN:
  1242.             case ENTER:
  1243.                 if (!(qual & IEQUALIFIER_REPEAT))
  1244.                     a = GAMEOVER;
  1245.             break;
  1246.             case NUMERICOPEN:
  1247.                 effect(FXCLICK);
  1248.                 setpointer(NORMAL);
  1249.                 underline(-1);
  1250.                 if (brush-- == 0 || brush > LASTOBJECT)
  1251.                     brush = LASTOBJECT;
  1252.                 stamp = brush;
  1253.                 break;
  1254.             case NUMERICCLOSE:
  1255.                 effect(FXCLICK);
  1256.                 setpointer(NORMAL);
  1257.                 underline(-1);
  1258.                 if (++brush > LASTOBJECT)
  1259.                     brush = 0;
  1260.                 stamp = brush;
  1261.                 break;
  1262.             break;
  1263.             case C:
  1264.                 effect(FXPENGUINDEATH); /* interesting */
  1265.                 x = FIELDX / 2;
  1266.                 y = FIELDY / 2;
  1267.             break;
  1268.             case ALPHAONE:
  1269.                 effect(FXCLICK);
  1270.                 stamp = GOLD;
  1271.                 break;
  1272.             case ALPHATWO:
  1273.                 effect(FXCLICK);
  1274.                 stamp = SILVER;
  1275.                 break;
  1276.             case ALPHATHREE:
  1277.                 effect(FXCLICK);
  1278.                 stamp = EMPTY;
  1279.                 break;
  1280.             case ALPHAFOUR:
  1281.                 effect(FXCLICK);
  1282.                 stamp = WOOD;
  1283.                 break;
  1284.             case ALPHAFIVE:
  1285.                 effect(FXCLICK);
  1286.                 stamp = STONE;
  1287.                 break;
  1288.             case ALPHASIX:
  1289.                 effect(FXCLICK);
  1290.                 stamp = METAL;
  1291.                 break;
  1292.             case ALPHASEVEN:
  1293.                 effect(FXCLICK);
  1294.                 stamp = ONE;
  1295.                 break;
  1296.             case ALPHAEIGHT:
  1297.                 effect(FXCLICK);
  1298.                 stamp = TWO;
  1299.                 break;
  1300.             case ALPHANINE:
  1301.                 effect(FXCLICK);
  1302.                 stamp = START;
  1303.                 break;
  1304.             case F1:
  1305.                 if (!(qual & IEQUALIFIER_REPEAT))
  1306.                 {    effect(FXCLICK);
  1307.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1308.                         fillfield(GOLD);
  1309.                     else setbrush(GOLD);
  1310.                 }
  1311.                 break;
  1312.             case F2:
  1313.                 if (!(qual & IEQUALIFIER_REPEAT))
  1314.                 {    effect(FXCLICK);
  1315.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1316.                         fillfield(SILVER);
  1317.                     else setbrush(SILVER);
  1318.                 }
  1319.                 break;
  1320.             case F3:
  1321.                 if (!(qual & IEQUALIFIER_REPEAT))
  1322.                 {    effect(FXCLICK);
  1323.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1324.                         fillfield(EMPTY);
  1325.                     else setbrush(EMPTY);
  1326.                 }
  1327.                 break;
  1328.             case F4:
  1329.                 if (!(qual & IEQUALIFIER_REPEAT))
  1330.                 {    effect(FXCLICK);
  1331.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1332.                         fillfield(WOOD);
  1333.                     else setbrush(WOOD);
  1334.                 }
  1335.                 break;
  1336.             case F5:
  1337.                 if (!(qual & IEQUALIFIER_REPEAT))
  1338.                 {    effect(FXCLICK);
  1339.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1340.                         fillfield(STONE);
  1341.                     else setbrush(STONE);
  1342.                 }
  1343.                 break;
  1344.             case F6:
  1345.                 if (!(qual & IEQUALIFIER_REPEAT))
  1346.                 {    effect(FXCLICK);
  1347.                     if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  1348.                         fillfield(METAL);
  1349.                     else setbrush(METAL);
  1350.                 }
  1351.                 break;
  1352.             case F7:
  1353.                 if (!(qual & IEQUALIFIER_REPEAT))
  1354.                 {    effect(FXCLICK);
  1355.                     setbrush(ONE);
  1356.                 }
  1357.                 break;
  1358.             case F8:
  1359.                 if (!(qual & IEQUALIFIER_REPEAT))
  1360.                 {    effect(FXCLICK);
  1361.                     setbrush(TWO);
  1362.                 }
  1363.                 break;
  1364.             case F9:
  1365.                 if (!(qual & IEQUALIFIER_REPEAT))
  1366.                 {    effect(FXCLICK);
  1367.                     setbrush(START);
  1368.                 }
  1369.                 break;
  1370.             case NUMERICZERO:
  1371.                 if (!(qual & IEQUALIFIER_REPEAT))
  1372.                 {    effect(FXCLICK);
  1373.                     if (!sticky)
  1374.                     {    sticky = TRUE;
  1375.                         stamp = brush;
  1376.                     } else
  1377.                     {       sticky = FALSE;
  1378.                                                 dot(x, y);
  1379.                 }       }
  1380.             break;
  1381.             case NUMERICDOT:
  1382.                 if (!(qual & IEQUALIFIER_REPEAT))
  1383.                 {    effect(FXCLICK);
  1384.                     stamp = brush;
  1385.                 }
  1386.             break;
  1387.             case NUMERICFOUR:
  1388.             case LEFT:
  1389.                 if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  1390.                     x = 0;
  1391.                 else if ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  1392.                     x = xwrap(x - ALTJUMP);
  1393.                 else
  1394.                     x = xwrap(x - 1);
  1395.                 if (sticky)
  1396.                     stamp = brush;
  1397.                 break;
  1398.             case NUMERICSIX:
  1399.             case RIGHT:
  1400.                 if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  1401.                     x = FIELDX;
  1402.                 else if ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  1403.                     x = xwrap(x + ALTJUMP);
  1404.                 else
  1405.                     x = xwrap(x + 1);
  1406.                 if (sticky)
  1407.                     stamp = brush;
  1408.                 break;
  1409.             case NUMERICEIGHT:
  1410.             case UP:
  1411.                 if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  1412.                     y = 0;
  1413.                 else if ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  1414.                     y = ywrap(y - ALTJUMP);
  1415.                 else
  1416.                     y = ywrap(y - 1);
  1417.                 if (sticky)
  1418.                     stamp = brush;
  1419.                 break;
  1420.             case NUMERICFIVE:
  1421.             case NUMERICTWO:
  1422.             case DOWN:
  1423.                 if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  1424.                     y = FIELDY;
  1425.                 else if ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  1426.                     y = ywrap(y + ALTJUMP);
  1427.                 else
  1428.                     y = ywrap(y + 1);
  1429.                 if (sticky)
  1430.                     stamp = brush;
  1431.                 break;
  1432.             case NUMERICSEVEN:
  1433.                 if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  1434.                 {    x = 0;
  1435.                     y = 0;
  1436.                 } else if ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  1437.                 {    x = xwrap(x - ALTJUMP);
  1438.                     y = ywrap(y - ALTJUMP);
  1439.                 } else
  1440.                 {    x = xwrap(x - 1);
  1441.                     y = ywrap(y - 1);
  1442.                 }
  1443.                 if (sticky)
  1444.                     stamp = brush;
  1445.                 break;
  1446.             case NUMERICNINE:
  1447.                 if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  1448.                 {    x = FIELDX;
  1449.                     y = 0;
  1450.                 } else if ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  1451.                 {    x = xwrap(x + ALTJUMP);
  1452.                     y = ywrap(y - ALTJUMP);
  1453.                 } else
  1454.                 {    x = xwrap(x + 1);
  1455.                     y = ywrap(y - 1);
  1456.                 }
  1457.                 if (sticky)
  1458.                     stamp = brush;
  1459.                 break;
  1460.             case NUMERICONE:
  1461.                 if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  1462.                 {    x = 0;
  1463.                     y = FIELDY;
  1464.                 } else if ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  1465.                 {    x = xwrap(x - ALTJUMP);
  1466.                     y = ywrap(y + ALTJUMP);
  1467.                 } else
  1468.                 {    x = xwrap(x - 1);
  1469.                     y = ywrap(y + 1);
  1470.                 }
  1471.                 if (sticky)
  1472.                     stamp = brush;
  1473.                 break;
  1474.             case NUMERICTHREE:
  1475.                 if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT) || (qual & IEQUALIFIER_CONTROL))
  1476.                 {    x = FIELDX;
  1477.                     y = FIELDY;
  1478.                 } else if ((qual & IEQUALIFIER_LALT) || (qual & IEQUALIFIER_RALT))
  1479.                 {    x = xwrap(x + ALTJUMP);
  1480.                     y = ywrap(y + ALTJUMP);
  1481.                 } else
  1482.                 {    x = xwrap(x + 1);
  1483.                     y = ywrap(y + 1);
  1484.                 }
  1485.                 if (sticky)
  1486.                     stamp = brush;
  1487.                 break;
  1488.             default:
  1489.                 break;
  1490.             }
  1491.             if (x != lastx || y != lasty)
  1492.             {    updatesquare(lastx, lasty);
  1493.                 if (stamp > LASTOBJECT)
  1494.                     dot(x, y);
  1495.             }
  1496.             break;
  1497.         case IDCMP_MOUSEBUTTONS:
  1498.             updatesquare(x, y);
  1499.             switch (code)
  1500.             {
  1501.             case SELECTUP:
  1502.                 leftdown = FALSE;
  1503.                 break;
  1504.             case SELECTDOWN:
  1505.                 effect(FXCLICK);
  1506.                 leftdown = TRUE;
  1507.                 break;
  1508.             case MENUUP:
  1509.                 rightdown = FALSE;
  1510.                 brush = oldbrush;
  1511.                 oldbrush = ANYTHING;
  1512.             break;
  1513.             default:
  1514.                 /* MENUDOWN */
  1515.             break;
  1516.             }
  1517.         break;
  1518.         case IDCMP_CLOSEWINDOW:
  1519.             cleanexit(EXIT_SUCCESS);
  1520.         break;
  1521.         case IDCMP_REFRESHWINDOW:
  1522.             GT_BeginRefresh(MainWindowPtr);
  1523.             GT_EndRefresh(MainWindowPtr, TRUE);
  1524.         break;
  1525.         default:
  1526.             /* IDCMP_MENUVERIFY, IDCMP_INTUITICKS, IDCMP_ACTIVEWINDOW */
  1527.         break;
  1528.     }    }
  1529.     else if (joy)
  1530.     {    if (GetMsg(JoyPortPtr))
  1531.         {    if (GameEvent.ie_Code == IECODE_LBUTTON)
  1532.                 stamp = brush;
  1533.             deltax = (SBYTE) GameEvent.ie_position.ie_xy.ie_x;
  1534.             deltay = (SBYTE) GameEvent.ie_position.ie_xy.ie_y;
  1535.             if (GameEvent.ie_Qualifier == IEQUALIFIER_LEFTBUTTON)
  1536.                 stamp = brush;
  1537.             sendreadrequest();
  1538.         }
  1539.         if (deltax || deltay)
  1540.         {    if (!timer)
  1541.             {    TimerRqPtr->tr_node.io_Command = TR_ADDREQUEST;
  1542.                 TimerRqPtr->tr_time.tv_secs    = 0;
  1543.                 TimerRqPtr->tr_time.tv_micro   = JOYDELAY;
  1544.                 SendIO(TimerRqPtr);
  1545.                 timer = TRUE;
  1546.             } else if (CheckIO(TimerRqPtr))
  1547.             {    lastx = x;
  1548.                 lasty = y;
  1549.                 x = xwrap(x + deltax);
  1550.                 y = ywrap(y + deltay);    
  1551.                 updatesquare(lastx, lasty);
  1552.                 dot(x, y);
  1553.                 timer = FALSE;
  1554.     }    }    }
  1555.     if (leftdown || rightdown)
  1556.     {    pointerx = xpixeltosquare(MainWindowPtr->MouseX);
  1557.         pointery = ypixeltosquare(MainWindowPtr->MouseY);
  1558.         if (valid(pointerx, pointery))
  1559.         {    x = pointerx;
  1560.             y = pointery;
  1561.             stamp = brush;
  1562.             updatesquare(lastx, lasty);
  1563.         }
  1564.         else if (leftdown && pointerx == GADGETX &&
  1565.         (pointery == GOLDGADGET
  1566.         || pointery == SILVERGADGET
  1567.         || pointery == EMPTYGADGET
  1568.         || pointery == WOODGADGET
  1569.         || pointery == STONEGADGET
  1570.         || pointery == METALGADGET
  1571.         || pointery == ONEGADGET
  1572.         || pointery == TWOGADGET
  1573.         || pointery == STARTGADGET))
  1574.         {    switch (pointery)
  1575.             {
  1576.             case GOLDGADGET:
  1577.                 setbrush(GOLD);
  1578.                 break;
  1579.             case SILVERGADGET:
  1580.                 setbrush(SILVER);
  1581.                 break;
  1582.             case EMPTYGADGET:
  1583.                 setbrush(EMPTY);
  1584.                 break;
  1585.             case WOODGADGET:
  1586.                 setbrush(WOOD);
  1587.                 break;
  1588.             case STONEGADGET:
  1589.                 setbrush(STONE);
  1590.                 break;
  1591.             case METALGADGET:
  1592.                 setbrush(METAL);
  1593.                 break;
  1594.             case ONEGADGET:
  1595.                 setbrush(ONE);
  1596.                 break;
  1597.             case TWOGADGET:
  1598.                 setbrush(TWO);
  1599.                 break;
  1600.             case STARTGADGET:
  1601.                 setbrush(START);
  1602.                 break;
  1603.             default:
  1604.                 break;
  1605.     }    }    }
  1606.  
  1607.     if (stamp != NOSQUARE)
  1608.     {    if (stamp == START && board[level][x][y] != TELEPORT)
  1609.         {    if (x != startx[level] || y != starty[level])
  1610.             {    draw(startx[level], starty[level], EMPTY);
  1611.                 board[level][startx[level]][starty[level]] = EMPTY;
  1612.                 draw(x, y, START);
  1613.                 startx[level] = x;
  1614.                 starty[level] = y;
  1615.                 modified = TRUE;
  1616.                 clearthem = TRUE;
  1617.         }    }
  1618.         else if (x != startx[level] || y != starty[level])
  1619.         {    if (stamp == ONE || stamp == TWO)
  1620.             {    if (teleport[level][partner(stamp - ONE)].alive == FALSE || x != teleport[level][partner(stamp - ONE)].x || y != teleport[level][partner(stamp - ONE)].y)
  1621.                 {    if (teleport[level][stamp - ONE].alive == TRUE)
  1622.                     {    draw(teleport[level][stamp - ONE].x, teleport[level][stamp - ONE].y, EMPTY);
  1623.                         board[level][teleport[level][stamp - ONE].x][teleport[level][stamp - ONE].y] = EMPTY;
  1624.                     } else
  1625.                         teleport[level][stamp - ONE].alive = TRUE;
  1626.                     board[level][x][y] = TELEPORT;
  1627.                     draw(x, y, stamp);
  1628.                     teleport[level][stamp - ONE].x = x;
  1629.                     teleport[level][stamp - ONE].y = y;
  1630.                     modified = TRUE;
  1631.                     clearthem = TRUE;
  1632.             }    }
  1633.             else
  1634.             {    if (board[level][x][y] == TELEPORT)
  1635.                     if (teleport[level][0].alive == TRUE && x == teleport[level][0].x && y == teleport[level][0].y)
  1636.                         teleport[level][0].alive = FALSE;
  1637.                     else teleport[level][1].alive = FALSE;
  1638.                 draw(x, y, stamp);
  1639.                 board[level][x][y] = stamp;
  1640.                                 if (sticky)
  1641.                                         dot(x, y);
  1642.                 modified = TRUE;
  1643.                 clearthem = TRUE;
  1644. }    }    }    }
  1645.  
  1646. /* exit to title screen */
  1647.  
  1648. OffMenu(MainWindowPtr, FULLMENUNUM(MN_EDIT, NOITEM, NOSUB));
  1649. if (timer)
  1650. {    AbortIO(TimerRqPtr);
  1651.     WaitIO(TimerRqPtr);
  1652. }
  1653. if (oldbrush != ANYTHING)
  1654.     brush = oldbrush;
  1655. setpointer(NORMAL);
  1656. if (clearthem)
  1657.     clearhiscores();
  1658. matchteleports();
  1659. }
  1660.  
  1661. MODULE void help(UBYTE type)
  1662. {       TEXT                 title[10];
  1663.         SWORD                x, y;
  1664.         UBYTE                i;
  1665.  
  1666.         effect(FXAMIGAN);
  1667.         if (type == ORB)
  1668.         {   strcpy(title, "Creatures");
  1669.             x = 112;
  1670.             y = 118;
  1671.         } else
  1672.         {   strcpy(title, "Objects");
  1673.             x = 640;
  1674.             y = 160;
  1675.         }
  1676.     if (!(HelpWindowPtr = (struct Window *) OpenWindowTags(NULL,
  1677.     WA_Left,            (SCREENXPIXEL / 2) - (x / 2),
  1678.     WA_Top,                (SCREENYPIXEL / 2) - (y / 2),
  1679.     WA_Width,            x,
  1680.     WA_Height,            y,
  1681.     WA_IDCMP,            IDCMP_CLOSEWINDOW | IDCMP_RAWKEY,
  1682.     WA_Title,            title,
  1683.     WA_Gadgets,            NULL,
  1684.     WA_CustomScreen,    ScreenPtr,
  1685.     WA_DragBar,            TRUE,
  1686.     WA_CloseGadget,        TRUE,
  1687.     WA_NoCareRefresh,    TRUE,
  1688.     WA_Activate,        TRUE,
  1689.     TAG_DONE)))
  1690.     {    say("Can't open help window!", RED);
  1691.         anykey(TRUE);
  1692.     } else
  1693.         {   SetAPen(HelpWindowPtr->RPort, WHITE);
  1694.             if (type == ORB)
  1695.             {   for (i = 0; i <= CREATUREHELPS; i++)
  1696.                 {   Image.ImageData = ImageData[creaturehelp[i].image];
  1697.                     DrawImage
  1698.             (   HelpWindowPtr->RPort,
  1699.                 &Image,
  1700.                 10,
  1701.                 15 + (i * 10)
  1702.                 );
  1703.                     Move(HelpWindowPtr->RPort, 26, 20 + (i * 10));
  1704.                     Text(HelpWindowPtr->RPort, creaturehelp[i].desc, strlen(creaturehelp[i].desc));
  1705.             }   }
  1706.             else /* assumes (type == AFFIXER) */
  1707.             {   for (i = 0; i <= LASTOBJECT; i++)
  1708.                 {   Image.ImageData = ImageData[i];
  1709.                     if (i <= LASTOBJECT / 2)
  1710.                     {   Move(HelpWindowPtr->RPort, 26, 20 + (i * 10));
  1711.                         DrawImage
  1712.                         (   HelpWindowPtr->RPort,
  1713.                             &Image,
  1714.                             10,
  1715.                             15 + (i * 10)
  1716.                         );
  1717.                     } else
  1718.                     {   Move(HelpWindowPtr->RPort, 354, 10 + ((i - (LASTOBJECT / 2)) * 10));
  1719.                         DrawImage
  1720.                         (   HelpWindowPtr->RPort,
  1721.                             &Image,
  1722.                             338,
  1723.                             5 + ((i - (LASTOBJECT / 2)) * 10)
  1724.                         );
  1725.                     }
  1726.                     Text(HelpWindowPtr->RPort, objectdesc[i], strlen(objectdesc[i]));
  1727.             }   }
  1728.             helploop();
  1729. }       }
  1730.  
  1731. MODULE void helpmanual(void)
  1732. {   /* Consider for 5.7: Asynchronous execution of MultiView using
  1733.     dos.library/SystemTagList(). And if we passed a lock to our PROGDIR: to
  1734.     MultiView, even better. */
  1735.     if (!Execute("SYS:Utilities/MultiView WormWars.guide", NULL, NULL))
  1736.         DisplayBeep(ScreenPtr);
  1737.     else ScreenToFront(ScreenPtr);
  1738. }
  1739.  
  1740. MODULE void helpabout(void)
  1741. {    SBYTE                    line;
  1742.     SLONG                    projectval;
  1743.     TEXT                    projectstring[6], ks[5] = "    ", wb[5] = "    ";
  1744.         ULONG                                   ksval = SysBase->lib_Version,
  1745.                                                 wbval = IconBase->lib_Version;
  1746.  
  1747.     effect(FXAMIGAN);
  1748.     if (!(HelpWindowPtr = (struct Window *) OpenWindowTags(NULL,
  1749.     WA_Left,            (SCREENXPIXEL / 2) - (ABOUTXPIXEL / 2),
  1750.     WA_Top,                (SCREENYPIXEL / 2) - (ABOUTYPIXEL / 2),
  1751.     WA_Width,            ABOUTXPIXEL,
  1752.     WA_Height,            ABOUTYPIXEL,
  1753.     WA_IDCMP,            IDCMP_CLOSEWINDOW | IDCMP_RAWKEY,
  1754.     WA_Title,            "About Worm Wars",
  1755.     WA_Gadgets,            NULL,
  1756.     WA_CustomScreen,    ScreenPtr,
  1757.     WA_DragBar,            TRUE,
  1758.     WA_CloseGadget,        TRUE,
  1759.     WA_NoCareRefresh,    TRUE,
  1760.     WA_Activate,        TRUE,
  1761.     TAG_DONE)))
  1762.     {    say("Can't open About... window!", RED);
  1763.         anykey(TRUE);
  1764.     } else
  1765.     {    /* calculate project size */
  1766.         
  1767.         projectval =
  1768.             11                                                         /* header */
  1769.         +    ((HISCORES + 1) * (9 + NAMELENGTH + DATELENGTH + TIMELENGTH))
  1770.                                                                      /* high scores */
  1771.         +    ((levels + 1) * (7 + ((FIELDX + 1) * (FIELDY + 1))))     /* level data */
  1772.         +    levels
  1773.         +    strlen(VERSION)
  1774.                 +       1;
  1775.  
  1776.                 switch(ksval)
  1777.                 {
  1778.                 case 37:
  1779.                         strcpy(ks, "2.04");
  1780.                 break;
  1781.                 case 38:
  1782.                         strcpy(ks, "2.1 ");
  1783.                 break;
  1784.                 case 39:
  1785.                         strcpy(ks, "3.0 ");
  1786.                 break;
  1787.                 case 40:
  1788.                         strcpy(ks, "3.1 ");
  1789.                 break;
  1790.                 default:
  1791.                         strcpy(ks, "4.0+");
  1792.                 break;
  1793.                 }
  1794.  
  1795.                 switch(wbval)
  1796.                 {
  1797.                 case 37:
  1798.                         strcpy(wb, "2.04");
  1799.                 break;
  1800.                 case 38:
  1801.                         strcpy(wb, "2.1 ");
  1802.                 break;
  1803.                 case 39:
  1804.                         strcpy(wb, "3.0 ");
  1805.                 break;
  1806.                 case 40:
  1807.                 case 41:
  1808.                 case 42:
  1809.                 case 43:
  1810.                         strcpy(wb, "3.1 ");
  1811.                 break;
  1812.                 case 44:
  1813.                         strcpy(wb, "3.5 ");
  1814.                 break;
  1815.                 default:
  1816.                         strcpy(wb, "4.0+");
  1817.                 break;
  1818.                 }
  1819.                 
  1820.         SetAPen(HelpWindowPtr->RPort, worm[rand() % 4].colour);
  1821.         RectFill(HelpWindowPtr->RPort, 8, 13, ABOUTXPIXEL - 11, ABOUTYPIXEL - 6);
  1822.         SetAPen(HelpWindowPtr->RPort, ABOUTSHADOW);
  1823.         Move(HelpWindowPtr->RPort, 7, ABOUTYPIXEL - 5);
  1824.         Draw(HelpWindowPtr->RPort, 7, 12);
  1825.         Draw(HelpWindowPtr->RPort, ABOUTXPIXEL - 10, 12);
  1826.         SetAPen(HelpWindowPtr->RPort, ABOUTSHINE);
  1827.         Draw(HelpWindowPtr->RPort, ABOUTXPIXEL - 10, ABOUTYPIXEL - 5);
  1828.         Draw(HelpWindowPtr->RPort, 8, ABOUTYPIXEL - 5);
  1829.         SetAPen(HelpWindowPtr->RPort, BLACK);
  1830.         SetDrMd(HelpWindowPtr->RPort, JAM1);
  1831.         for (line = 0; line <= ABOUTLINES; line++)
  1832.         {    Move(HelpWindowPtr->RPort, about[line].x, about[line].y);
  1833.             Text(HelpWindowPtr->RPort, about[line].text, (SBYTE) strlen(about[line].text));
  1834.         }
  1835.         stcl_d(projectstring, projectval);
  1836.         align(projectstring, 5, ' ');
  1837.         Move(HelpWindowPtr->RPort, PROJECTX, PROJECTY);
  1838.         Text(HelpWindowPtr->RPort, projectstring, 5);
  1839.                 Move(HelpWindowPtr->RPort, KICKSTARTX, KICKSTARTY);
  1840.                 Text(HelpWindowPtr->RPort, ks, 4);
  1841.                 Move(HelpWindowPtr->RPort, WORKBENCHX, WORKBENCHY);
  1842.                 Text(HelpWindowPtr->RPort, wb, 4);
  1843.  
  1844.         DrawBevelBox(HelpWindowPtr->RPort, 18, 21, 47, 22, GT_VisualInfo, VisualInfoPtr);
  1845.         DrawImage(HelpWindowPtr->RPort, &About, 19, 22);
  1846.  
  1847.                 helploop();
  1848. }        }
  1849.  
  1850. MODULE void helploop(void)
  1851. {   ABOOL                done = FALSE;
  1852.     UWORD                code, qual;
  1853.     ULONG                class;
  1854.     struct IntuiMessage* MsgPtr;
  1855.  
  1856.         while(!done)
  1857.         {    Wait(1L << HelpWindowPtr->UserPort->mp_SigBit);
  1858.             while (MsgPtr = (struct IntuiMessage *) GetMsg(HelpWindowPtr->UserPort))
  1859.             {    class = MsgPtr->Class;
  1860.                 code  = MsgPtr->Code;
  1861.                 qual  = MsgPtr->Qualifier;
  1862.                 ReplyMsg(MsgPtr);
  1863.                 switch(class)
  1864.                 {
  1865.                 case IDCMP_CLOSEWINDOW:
  1866.                     done = TRUE;
  1867.                     break;
  1868.                 case IDCMP_RAWKEY:
  1869.                        if (code == SPACEBAR || code == RETURN || code == ENTER || code == HELP)
  1870.                        done = TRUE;
  1871.                     else if (code == ESCAPE)
  1872.                         if (qual & IEQUALIFIER_LSHIFT || qual & IEQUALIFIER_RSHIFT)
  1873.                         {    if (verify())
  1874.                             {   CloseWindow(HelpWindowPtr);
  1875.                                 cleanexit(EXIT_SUCCESS);
  1876.                         }    }
  1877.                         else done = TRUE;
  1878.                     break;
  1879.                 default:
  1880.                     break;
  1881.         }   }   }
  1882.     CloseWindow(HelpWindowPtr);
  1883.     clearkybd();
  1884. }
  1885.  
  1886. AGLOBAL void fileopen(ABOOL revert)
  1887. {   TEXT temp1[81] = {"Opened "}, temp2[3], newpathname[255];
  1888.  
  1889.     strcpy(newpathname, pathname);
  1890.     if (revert || (AslRequestTags(ASLRqPtr, ASL_Hail, "Open Fieldset", ASL_FuncFlags, FILF_PATGAD, TAG_DONE) && *(ASLRqPtr->rf_File)))
  1891.     {   if (!revert)
  1892.         {   strcpy(newpathname, ASLRqPtr->rf_Dir);
  1893.             AddPart(newpathname, ASLRqPtr->rf_File, 254);
  1894.         }
  1895.         if (!loadfields(newpathname))
  1896.         {   strcpy(pathname, newpathname);
  1897.             strcat(temp1, pathname);
  1898.             strcat(temp1, " (");
  1899.             stci_d(temp2, levels);
  1900.             strcat(temp1, temp2);
  1901.             strcat(temp1, " levels).");
  1902.             say(temp1, WHITE);
  1903.             if (a == FIELDEDIT)
  1904.                 turborender();
  1905.             else hiscores();
  1906.         } else
  1907.         {   strcpy(temp1, "Couldn't open ");
  1908.             strcat(temp1, newpathname);
  1909.             strcat(temp1, "!");
  1910.             say(temp1, WHITE);
  1911.     }   }
  1912.     if (a == GAMEOVER)
  1913.         anykey(TRUE);
  1914. }
  1915.  
  1916. AGLOBAL void filesaveas(ABOOL flag)
  1917. {    ABOOL    cont = TRUE;
  1918.     TEXT    newpathname[255], temp1[SAYLIMIT + 1], temp2[3];
  1919.         struct DiskObject* InfoHandle;
  1920.  
  1921.     /* flag is TRUE for 'save as...', FALSE for 'save'. */
  1922.  
  1923.     strcpy(newpathname, pathname);
  1924.     if (flag)
  1925.         if (AslRequestTags(ASLRqPtr, ASL_Hail, "Save Fieldset", ASL_FuncFlags, FILF_PATGAD | FILF_SAVE, TAG_DONE) && *(ASLRqPtr->rf_File) != 0)
  1926.         {   strcpy(newpathname, ASLRqPtr->rf_Dir);
  1927.             AddPart(newpathname, ASLRqPtr->rf_File, 254);
  1928.         } else cont = FALSE;
  1929.     if (cont)
  1930.     {    strcpy(temp1, "Saving ");
  1931.     strcat(temp1, newpathname);
  1932.     strcat(temp1, "...");
  1933.     say(temp1, WHITE);
  1934.     if (savefields(newpathname))
  1935.         {   strcpy(pathname, newpathname);
  1936.             if (icons)
  1937.             {   InfoHandle = GetDiskObjectNew(DEFAULTSET);
  1938.                 InfoHandle->do_CurrentX = NO_ICON_POSITION;
  1939.                 InfoHandle->do_CurrentY = NO_ICON_POSITION;
  1940.                 if (!PutDiskObject(pathname, InfoHandle))
  1941.                 {   say("Couldn't write .info file!", RED);
  1942.                     anykey(TRUE);
  1943.             }   }
  1944.             strcpy(temp1, "Saved ");
  1945.             strcat(temp1, pathname);
  1946.             strcat(temp1, " (");
  1947.             stci_d(temp2, levels);
  1948.             strcat(temp1, temp2);
  1949.             strcat(temp1, " levels).");
  1950.         } else
  1951.         {   strcpy(temp1, "Couldn't save ");
  1952.             strcat(temp1, newpathname);
  1953.             strcat(temp1, "!");
  1954.         }
  1955.         say(temp1, WHITE);
  1956.         if (a == GAMEOVER)
  1957.             anykey(TRUE);
  1958. }   }
  1959.  
  1960. MODULE void freefx(void)
  1961. {    SBYTE i;
  1962.  
  1963.         stopfx();
  1964.     if (!AudioClosed)
  1965.     {    CloseDevice((struct IORequest *) AudioRqPtr[0]);
  1966.         AudioClosed = TRUE;
  1967.     }
  1968.     for (i = 0; i <= 3; i++)
  1969.     {    if (AudioRqPtr[i])
  1970.         {    DeleteIORequest(AudioRqPtr[i]);
  1971.             AudioRqPtr[i] = NULL;
  1972.         }
  1973.         if (AudioPortPtr[i])
  1974.         {    DeleteMsgPort(AudioPortPtr[i]);
  1975.             AudioPortPtr[i] = NULL;
  1976.     }    }
  1977.     if (fbase)
  1978.     {    FreeMem(fbase, fsize);
  1979.         fbase = NULL;
  1980.     }
  1981.     if (FilePtr)
  1982.     {   Close(FilePtr);
  1983.         FilePtr = NULL;
  1984. }    }
  1985.  
  1986. void gameinput(void)
  1987. {        ABOOL                    done;
  1988.         UWORD                    code, qual;
  1989.         ULONG                    class;
  1990.         struct IntuiMessage*    MsgPtr;
  1991.         SBYTE                   keyplayer;
  1992.         UBYTE                   which;
  1993.  
  1994. for (which = 0; which <= NUMKEYS; which++)
  1995.     key[which].down = FALSE;
  1996.  
  1997. /* keyboard */
  1998.  
  1999. while (MsgPtr = (struct IntuiMessage *) GetMsg(MainWindowPtr->UserPort))
  2000. {    class  = MsgPtr->Class;
  2001.     code   = MsgPtr->Code;
  2002.     qual   = MsgPtr->Qualifier;
  2003.     ReplyMsg(MsgPtr);
  2004.     if (class == IDCMP_RAWKEY && (!(qual & IEQUALIFIER_REPEAT)) && code < KEYUP)
  2005.     {    switch(code) {
  2006.         case M:
  2007.             toggle(M);
  2008.         break;
  2009.         case F:
  2010.             toggle(F);
  2011.         break;
  2012.         case P:
  2013.             clearkybd();
  2014.             say("Paused...press P to unpause", WHITE);
  2015.             pausetimer();
  2016.             done = FALSE;
  2017.             while (!done)
  2018.             {    Wait(1L << MainWindowPtr->UserPort->mp_SigBit);
  2019.                 while (MsgPtr = (struct IntuiMessage *) GetMsg(MainWindowPtr->UserPort))
  2020.                 {    class = MsgPtr->Class;
  2021.                     code  = MsgPtr->Code;
  2022.                     qual  = MsgPtr->Qualifier;
  2023.                     ReplyMsg(MsgPtr);
  2024.                     if (class == IDCMP_RAWKEY && (!(qual & IEQUALIFIER_REPEAT)))
  2025.                     {    if (code == ESCAPE)
  2026.                         {    if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  2027.                             {    if (verify())
  2028.                                     cleanexit(EXIT_SUCCESS);
  2029.                             } else
  2030.                             {    a = GAMEOVER;
  2031.                                 done = TRUE;
  2032.                                 worm[0].lives = worm[1].lives = worm[2].lives = worm[3].lives = 0;
  2033.                         }    }
  2034.                         else if (code == M)
  2035.                             toggle(M);
  2036.                         else if (code == F)
  2037.                             toggle(F);
  2038.                         else if (code == P)
  2039.                         {    say("Unpaused", WHITE);
  2040.                             done = TRUE;
  2041.             }    }    }    }
  2042.             unpausetimer();
  2043.         break;
  2044.         case ESCAPE:
  2045.             if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  2046.             {    if (verify())
  2047.                     cleanexit(EXIT_SUCCESS);
  2048.             } else
  2049.             {    a = GAMEOVER;
  2050.                 worm[0].lives = worm[1].lives = worm[2].lives = worm[3].lives = 0;
  2051.             }
  2052.         break;
  2053.         default:
  2054.             for (which = 0; which <= NUMKEYS; which++)
  2055.                 if (code == key[which].scancode)
  2056.                     key[which].down = TRUE;
  2057.         break;
  2058.     }    }    
  2059.     else if (class == IDCMP_CLOSEWINDOW)
  2060.         cleanexit(EXIT_SUCCESS);
  2061.     else if (class == IDCMP_REFRESHWINDOW)
  2062.     {   GT_BeginRefresh(MainWindowPtr);
  2063.         GT_EndRefresh(MainWindowPtr, TRUE);
  2064. }   }
  2065. /* Received but ignored: IDCMP_ACTIVEWINDOW, IDCMP_MOUSEBUTTONS and
  2066. IDCMP_INTUITICKS. */
  2067.  
  2068. for (which = 0; which <= NUMKEYS; which++)
  2069. {    if (key[which].down)
  2070.     {    if (key[which].special == ONEHUMAN)
  2071.         {    if (worm[0].control == HUMAN && worm[1].control != HUMAN)
  2072.                 wormqueue(0, key[which].deltax, key[which].deltay);
  2073.             else if (worm[0].control != HUMAN && worm[1].control == HUMAN)
  2074.                 wormqueue(1, key[which].deltax, key[which].deltay);
  2075.         } else if (key[which].special == MOVE || key[which].special == AMMO)
  2076.         {   if (worm[key[which].player].control == HUMAN)
  2077.                 keyplayer = key[which].player;
  2078.             else if (key[which].player == 1 && worm[0].control == HUMAN && worm[1].control != HUMAN)
  2079.                 keyplayer = 0;
  2080.             else if (key[which].player == 0 && worm[1].control == HUMAN && worm[0].control != HUMAN)
  2081.                 keyplayer = 1;
  2082.             else keyplayer = -1;
  2083.             if (keyplayer != -1)
  2084.                 wormqueue(keyplayer, key[which].deltax, key[which].deltay);
  2085.         } else if (worm[1].lives) /* assumes key[which].special == TRAINER */
  2086.             train(key[which].scancode);
  2087. }    }
  2088.  
  2089. /* joystick */
  2090.  
  2091. if (worm[2].control == HUMAN)
  2092.     while (GetMsg(JoyPortPtr))
  2093.     {    if (GameEvent.ie_position.ie_xy.ie_x != 0 || GameEvent.ie_position.ie_xy.ie_y != 0)
  2094.             wormqueue(2, GameEvent.ie_position.ie_xy.ie_x, GameEvent.ie_position.ie_xy.ie_y);
  2095.         if (GameEvent.ie_Code == IECODE_LBUTTON)
  2096.             wormqueue(2, 0, 0);
  2097.         sendreadrequest();
  2098. }    }
  2099.  
  2100. void hiscores(void)
  2101. {    SBYTE                    which;
  2102.     TEXT                    tempstring[NAMELENGTH + 1];
  2103.  
  2104. /* render hiscores
  2105.  
  2106. #################################################### # = shadow
  2107. #   #   #   #                      #     #         % % = shine
  2108. #   #   #   #                      #     #         %
  2109. #   #   #   #                      #     #         %
  2110. #   #   #   #                      #     #         %
  2111. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */
  2112.  
  2113. SetDrMd(MainWindowPtr->RPort, JAM1);
  2114. for (which = 0; which <= HISCORES; which++)
  2115. {    if (hiscore[which].player == -1)
  2116.         SetAPen(MainWindowPtr->RPort, LIGHTGREY);
  2117.     else SetAPen(MainWindowPtr->RPort, worm[hiscore[which].player].colour);
  2118.     RectFill(MainWindowPtr->RPort, 104, 105 + which * HISCOREDISTANCE, 536, 114 + which * HISCOREDISTANCE);
  2119.     if (hiscore[which].player == 0)
  2120.         SetAPen(MainWindowPtr->RPort, DARKGREEN);
  2121.     else if (hiscore[which].player == 1)
  2122.         SetAPen(MainWindowPtr->RPort, DARKRED);
  2123.     else if (hiscore[which].player == 2)
  2124.         SetAPen(MainWindowPtr->RPort, DARKBLUE);
  2125.     else if (hiscore[which].player == 3)
  2126.         SetAPen(MainWindowPtr->RPort, DARKYELLOW);
  2127.     else SetAPen(MainWindowPtr->RPort, DARKGREY);
  2128.     Move(MainWindowPtr->RPort, 103, 115 + which * HISCOREDISTANCE);
  2129.     Draw(MainWindowPtr->RPort, 103, 104 + which * HISCOREDISTANCE);
  2130.     Draw(MainWindowPtr->RPort, 537, 104 + which * HISCOREDISTANCE);
  2131.  
  2132.     if (hiscore[which].player != -1)
  2133.     {    /* divider bars */
  2134.     
  2135.         Move(MainWindowPtr->RPort, 182 - 55, 104 + which * HISCOREDISTANCE);
  2136.         Draw(MainWindowPtr->RPort, 182 - 55, 114 + which * HISCOREDISTANCE);
  2137.         Move(MainWindowPtr->RPort, 254 - 55, 104 + which * HISCOREDISTANCE);
  2138.         Draw(MainWindowPtr->RPort, 254 - 55, 114 + which * HISCOREDISTANCE);
  2139.         Move(MainWindowPtr->RPort, 290 - 55, 104 + which * HISCOREDISTANCE);
  2140.         Draw(MainWindowPtr->RPort, 290 - 55, 114 + which * HISCOREDISTANCE);
  2141.         Move(MainWindowPtr->RPort, 416, 104 + which * HISCOREDISTANCE);
  2142.         Draw(MainWindowPtr->RPort, 416, 114 + which * HISCOREDISTANCE);
  2143.         Move(MainWindowPtr->RPort, 464, 104 + which * HISCOREDISTANCE);
  2144.         Draw(MainWindowPtr->RPort, 464, 114 + which * HISCOREDISTANCE);
  2145.     }
  2146.     
  2147.     SetAPen(MainWindowPtr->RPort, WHITE);
  2148.     Move(MainWindowPtr->RPort, 159 - 55, 115 + which * HISCOREDISTANCE);
  2149.     Draw(MainWindowPtr->RPort, 482 + 55, 115 + which * HISCOREDISTANCE);
  2150.     Draw(MainWindowPtr->RPort, 482 + 55, 105 + which * HISCOREDISTANCE);
  2151.     SetAPen(MainWindowPtr->RPort, BLACK);
  2152.  
  2153.     if (hiscore[which].player != -1)
  2154.     {    stci_d(tempstring, which + 1);
  2155.         tempstring[1] = '.';
  2156.         Move(MainWindowPtr->RPort, 161 - 55, 112 + which * HISCOREDISTANCE);
  2157.         Text(MainWindowPtr->RPort, tempstring, 2);
  2158.         stci_d(tempstring, hiscore[which].score);
  2159.         align(tempstring, 7, ' ');
  2160.         Move(MainWindowPtr->RPort, 193 - 55, 112 + which * HISCOREDISTANCE);
  2161.         Text(MainWindowPtr->RPort, tempstring, 7);
  2162.         if (hiscore[which].level == -1)
  2163.             strcpy(tempstring, "All");
  2164.         else
  2165.         {    stci_d(tempstring, hiscore[which].level);
  2166.             align(tempstring, 3, ' ');
  2167.         }
  2168.         Move(MainWindowPtr->RPort, 206, 112 + which * HISCOREDISTANCE);
  2169.         Text(MainWindowPtr->RPort, tempstring, 3);
  2170.         Move(MainWindowPtr->RPort, 241, 112 + which * HISCOREDISTANCE);
  2171.         Text(MainWindowPtr->RPort, hiscore[which].name, strlen(hiscore[which].name));
  2172.         Move(MainWindowPtr->RPort, 418, 112 + which * HISCOREDISTANCE);
  2173.         Text(MainWindowPtr->RPort, hiscore[which].time, strlen(hiscore[which].time));
  2174.         Move(MainWindowPtr->RPort, 466, 112 + which * HISCOREDISTANCE);
  2175.         Text(MainWindowPtr->RPort, hiscore[which].date, strlen(hiscore[which].date));
  2176. }    }
  2177. SetDrMd(MainWindowPtr->RPort, JAM2);
  2178. }
  2179.  
  2180. void hiscorenames(void)
  2181. {
  2182. ULONG                    class;
  2183. ABOOL                    done;
  2184. SBYTE                    which;
  2185. struct IntuiMessage*    MsgPtr;
  2186.  
  2187. for (which = 0; which <= HISCORES; which++)
  2188.     if (hiscore[which].fresh)
  2189.     {    GT_SetGadgetAttrs(StringGadgetPtr[which], MainWindowPtr, NULL, GA_Disabled, FALSE, GTST_String, worm[hiscore[which].player].name, TAG_DONE);
  2190.         ActivateGadget(StringGadgetPtr[which], MainWindowPtr, NULL);
  2191.         done = FALSE;
  2192.         while (!done)
  2193.         {    while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
  2194.             {    class = MsgPtr->Class;
  2195.                 GT_ReplyIMsg(MsgPtr);
  2196.                 if (class == IDCMP_GADGETUP)
  2197.                     done = TRUE;
  2198.                 else if (class == IDCMP_MOUSEBUTTONS)
  2199.                     ActivateGadget(StringGadgetPtr[which], MainWindowPtr, NULL);
  2200.                 else if (class == IDCMP_REFRESHWINDOW)
  2201.                 {    GT_BeginRefresh(MainWindowPtr);
  2202.                     GT_EndRefresh(MainWindowPtr, TRUE);
  2203.         }    }    }
  2204.         GT_SetGadgetAttrs(StringGadgetPtr[which], MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
  2205.         effect(FXHISCORE);
  2206.         strcpy(hiscore[which].name, ((struct StringInfo *) (StringGadgetPtr[which]->SpecialInfo))->Buffer);
  2207.         if (hiscore[which].name[0] >= 97 && hiscore[which].name[0] <= 123)
  2208.             hiscore[which].name[0] -= 32;
  2209.         strcpy(worm[hiscore[which].player].name, hiscore[which].name);
  2210.         hiscore[which].fresh = FALSE;
  2211.         hiscores();
  2212. }    }
  2213.  
  2214. MODULE ABOOL beginfx(void)
  2215. {           SBYTE    i;
  2216.     PERSIST    UBYTE    chan[]    = {15};
  2217.  
  2218.     for (i = 0; i <= 3; i++)
  2219.     {   eversent[i] = FALSE;
  2220.         if (!(AudioPortPtr[i] = (struct MsgPort *) CreateMsgPort()))
  2221.         {   freefx();
  2222.             draw(MUSICICON, ICONY, BLACKENED);
  2223.             mode = FALSE;
  2224.             say("No port for effects!", RED);
  2225.             anykey(TRUE);
  2226.             return FALSE;
  2227.         } else if (!(AudioRqPtr[i] = (struct IOAudio *) CreateIORequest(AudioPortPtr[i], sizeof(struct IOAudio))))
  2228.         {   freefx();
  2229.             draw(MUSICICON, ICONY, BLACKENED);
  2230.             mode = FALSE;
  2231.             say("No I/O memory for effects!", RED);
  2232.             anykey(TRUE);
  2233.             return FALSE;
  2234.     }   }
  2235.     AudioRqPtr[0]->ioa_Request.io_Message.mn_ReplyPort      = AudioPortPtr[0];
  2236.     AudioRqPtr[0]->ioa_Request.io_Message.mn_Node.ln_Pri    = 127;
  2237.     AudioRqPtr[0]->ioa_AllocKey                             = 0;
  2238.     AudioRqPtr[0]->ioa_Data                                 = chan;
  2239.     AudioRqPtr[0]->ioa_Length                               = 1;
  2240.     if (AudioClosed = OpenDevice(AUDIONAME, 0L, (struct IORequest *) AudioRqPtr[0], 0L))
  2241.     {   freefx();
  2242.         draw(MUSICICON, ICONY, BLACKENED);
  2243.         mode = FALSE;
  2244.         say("Can't allocate all channels for effects!", RED);
  2245.         anykey(TRUE);
  2246.         return FALSE;
  2247.     } else
  2248.     {   for (i = 1; i <= 3; i++)
  2249.             CopyMem(AudioRqPtr[0], AudioRqPtr[i], sizeof(struct IOAudio));
  2250.         return TRUE;
  2251. }   }
  2252.  
  2253. void resettime(void)
  2254. {    GetSysTime(StartValPtr);
  2255.         srand((UWORD) StartValPtr->tv_micro);
  2256. }
  2257.  
  2258. void rundown(SBYTE player)
  2259. {    TEXT                 tempstring[6];
  2260.     SBYTE                i, j, x, y;
  2261.     UWORD                counter = 0, code, qual;
  2262.     ABOOL                done = FALSE;
  2263.     ULONG                levelbonus, timebonus, tailbonus, class;
  2264.         UBYTE                multiply = worm[player].multi * players;
  2265.     struct IntuiMessage* MsgPtr;
  2266.  
  2267.     clearscreen();
  2268.     SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2269.  
  2270.     Image.ImageData = ImageData[TREASURE];
  2271.     DrawImage(MainWindowPtr->RPort, &Image, 201, 103);
  2272.     Move(MainWindowPtr->RPort, 218, 108);
  2273.     Text(MainWindowPtr->RPort, "Level Bonus:    ## x ##00 =", 27);
  2274.         stci_d(tempstring, multiply);
  2275.     align(tempstring, 2, ' ');
  2276.     Move(MainWindowPtr->RPort, 218 + (FONTX * 21), 108);
  2277.     Text(MainWindowPtr->RPort, tempstring, 2);
  2278.     stci_d(tempstring, level - 1);
  2279.     align(tempstring, 2, ' ');
  2280.     Move(MainWindowPtr->RPort, 218 + (FONTX * 16), 108);
  2281.     Text(MainWindowPtr->RPort, tempstring, 2);
  2282.  
  2283.     Image.ImageData = ImageData[CLOCK];
  2284.     DrawImage(MainWindowPtr->RPort, &Image, 201, 111);
  2285.     Move(MainWindowPtr->RPort, 218, 116);
  2286.     Text(MainWindowPtr->RPort, " Time Bonus: ##:## x  ##0 =", 27);
  2287.         stci_d(tempstring, multiply);
  2288.     align(tempstring, 2, ' ');
  2289.     Move(MainWindowPtr->RPort, 226 + (FONTX     * 21), 116);
  2290.     Text(MainWindowPtr->RPort, tempstring, 2);
  2291.     stci_d(tempstring, secondsleft / 60);
  2292.     align(tempstring, 2, ' ');
  2293.     Move(MainWindowPtr->RPort, 226 + (FONTX * 12), 116);
  2294.     Text(MainWindowPtr->RPort, tempstring, 2);
  2295.     stci_d(tempstring, secondsleft % 60);
  2296.     align(tempstring, 2, '0');
  2297.     Move(MainWindowPtr->RPort, 226 + (FONTX * 15), 116);
  2298.     Text(MainWindowPtr->RPort, tempstring, 2);
  2299.  
  2300.     Image.ImageData = ImageData[FIRSTTAIL + player];
  2301.     DrawImage(MainWindowPtr->RPort, &Image, 201, 119);
  2302.     Move(MainWindowPtr->RPort, 218, 124);
  2303.     Text(MainWindowPtr->RPort, " Tail Bonus:  #### x   ## =", 27);
  2304.         stci_d(tempstring, multiply);
  2305.     align(tempstring, 2, ' ');
  2306.         Move(MainWindowPtr->RPort, 226 + (FONTX * 22), 124);
  2307.         Text(MainWindowPtr->RPort, tempstring, 2);
  2308.     for (x = 0; x <= FIELDX; x++)
  2309.         for (y = 0; y <= FIELDY; y++)
  2310.             if (field[x][y] == FIRSTTAIL + player)
  2311.                 counter++;
  2312.     stci_d(tempstring, counter);
  2313.     align(tempstring, 4, ' ');
  2314.     Move(MainWindowPtr->RPort, 226 + (FONTX * 13), 124);
  2315.     Text(MainWindowPtr->RPort, tempstring, 4);
  2316.  
  2317.     levelbonus = (level - 1) * 100 * multiply;
  2318.     timebonus = secondsleft * 10 * multiply;
  2319.     tailbonus = counter * multiply;
  2320.  
  2321.     for (i = 0; i <= 3; i++)
  2322.         if (worm[i].control != NONE)
  2323.             for (j = 0; j <= LASTOBJECT; j++)
  2324.                 stat(i, j);
  2325.  
  2326.     while (!done)
  2327.     {   while (MsgPtr = (struct IntuiMessage *) GetMsg(MainWindowPtr->UserPort))
  2328.         {   class  = MsgPtr->Class;
  2329.         code   = MsgPtr->Code;
  2330.         qual   = MsgPtr->Qualifier;
  2331.         ReplyMsg(MsgPtr);
  2332.             if (class == IDCMP_RAWKEY && (!(qual & IEQUALIFIER_REPEAT)) && code < KEYUP)
  2333.                 done = TRUE;
  2334.         }
  2335.         if (done)
  2336.     {   wormscore
  2337.             (   player,
  2338.                 (levelbonus / multiply) +
  2339.                 ( timebonus / multiply) +
  2340.                 ( tailbonus / multiply)
  2341.             );
  2342.             levelbonus = timebonus = tailbonus = 0;
  2343.         }
  2344.         SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2345.         stci_d(tempstring, levelbonus);
  2346.         align(tempstring, 5, ' ');
  2347.         Move(MainWindowPtr->RPort, 218 + (FONTX * 27), 108);
  2348.         Text(MainWindowPtr->RPort, tempstring, 5);
  2349.  
  2350.         stci_d(tempstring, timebonus);
  2351.         align(tempstring, 5, ' ');
  2352.         Move(MainWindowPtr->RPort, 226 + (FONTX * 26), 116);
  2353.         Text(MainWindowPtr->RPort, tempstring, 5);
  2354.  
  2355.         stci_d(tempstring, tailbonus);
  2356.         align(tempstring, 5, ' ');
  2357.         Move(MainWindowPtr->RPort, 226 + (FONTX * 26), 124);
  2358.         Text(MainWindowPtr->RPort, tempstring, 5);
  2359.  
  2360.         done = TRUE;
  2361.         if (levelbonus)
  2362.         {   levelbonus -= multiply;
  2363.             wormscore(player, 1);
  2364.             done = FALSE;
  2365.         }
  2366.         if (timebonus)
  2367.         {   timebonus -= multiply;
  2368.             wormscore(player, 1);
  2369.             done = FALSE;
  2370.         }
  2371.         if (tailbonus)
  2372.         {   tailbonus -= multiply;
  2373.             wormscore(player, 1);
  2374.             done = FALSE;
  2375.         }
  2376.         effect(FXRUNDOWN);
  2377.     }
  2378.     clearkybd();
  2379.     effect(FXENDOFLEVEL);
  2380.     anykey(FALSE);
  2381. }
  2382.  
  2383. void say(STRPTR sentence, COLOUR colour)
  2384. {   SBYTE length = (SBYTE) strlen(sentence);
  2385.  
  2386.     /* truncate text */
  2387.  
  2388.     if (length > SAYLIMIT)
  2389.         *(sentence + SAYLIMIT - 1) = *(sentence + SAYLIMIT - 2) = *(sentence + SAYLIMIT - 3) = '.';
  2390.  
  2391.     /* clear areas to left, right and top of text, respectively */
  2392.  
  2393.     SetAPen(MainWindowPtr->RPort, BLACK);
  2394.     RectFill
  2395.     (   MainWindowPtr->RPort,
  2396.         SAYSTARTXPIXEL,
  2397.         2,
  2398.         (SCREENXPIXEL / 2) - (length * FONTX / 2),
  2399.         10
  2400.     );
  2401.     RectFill
  2402.     (   MainWindowPtr->RPort,
  2403.         (SCREENXPIXEL / 2) + (length * FONTX / 2) + 1,
  2404.         2,
  2405.         SAYENDXPIXEL,
  2406.         10
  2407.     );
  2408.     Move(MainWindowPtr->RPort, (SCREENXPIXEL / 2) - (length * FONTX / 2), 2);
  2409.     Draw(MainWindowPtr->RPort, (SCREENXPIXEL / 2) + (length * FONTX / 2), 2);
  2410.  
  2411.     /* render shadow text */
  2412.     
  2413.     SetAPen(MainWindowPtr->RPort, MEDIUMGREY);
  2414.     Move(MainWindowPtr->RPort, (SCREENXPIXEL / 2) - (length * FONTX / 2) + 1, FONTY + 1);
  2415.     Text(MainWindowPtr->RPort, sentence, length);
  2416.     
  2417.     /* render actual text */
  2418.     
  2419.     SetDrMd(MainWindowPtr->RPort, JAM1);
  2420.     SetAPen(MainWindowPtr->RPort, colour);
  2421.     Move(MainWindowPtr->RPort, (SCREENXPIXEL / 2) - (length * FONTX / 2), FONTY);
  2422.     Text(MainWindowPtr->RPort, sentence, length);
  2423.     SetDrMd(MainWindowPtr->RPort, JAM2);
  2424. }
  2425.     
  2426. void sendreadrequest(void)
  2427. {    JoyRqPtr->io_Command    = GPD_READEVENT;
  2428.     JoyRqPtr->io_Flags        = NULL;
  2429.     JoyRqPtr->io_Length        = sizeof(struct InputEvent);
  2430.     JoyRqPtr->io_Data        = (APTR) &GameEvent;
  2431.     SendIO(JoyRqPtr);
  2432. }
  2433.  
  2434. MODULE void setpointer(SBYTE pointer) {
  2435. switch (pointer) {
  2436. case GOLD:
  2437.     SetRGB4(&ScreenPtr->ViewPort, 17, 10,  8,  3);        /* fill */
  2438.     SetRGB4(&ScreenPtr->ViewPort, 18,  8,  4,  2);        /* shadow */
  2439.     SetRGB4(&ScreenPtr->ViewPort, 19, 12, 12,  2);        /* shine */
  2440.     SetPointer(MainWindowPtr, &CustomPointer, 6, 5, -3, -2);
  2441.     break;
  2442. case SILVER:
  2443.     SetRGB4(&ScreenPtr->ViewPort, 17, 10, 10, 10);        /* fill */
  2444.     SetRGB4(&ScreenPtr->ViewPort, 18,  6,  6,  6);        /* shadow */
  2445.     SetRGB4(&ScreenPtr->ViewPort, 19, 15, 15, 15);        /* shine */
  2446.     SetPointer(MainWindowPtr, &CustomPointer, 6, 5, -3, -2);
  2447.     break;
  2448. case EMPTY:
  2449.     SetRGB4(&ScreenPtr->ViewPort, 17,  2,  2,  2);        /* fill */
  2450.     SetRGB4(&ScreenPtr->ViewPort, 18,  0,  0,  0);        /* shadow */
  2451.     SetRGB4(&ScreenPtr->ViewPort, 19,  6,  6,  6);        /* shine */
  2452.     SetPointer(MainWindowPtr, &CustomPointer, 6, 5, -3, -2);
  2453.     break;
  2454. case WOOD:
  2455.     SetRGB4(&ScreenPtr->ViewPort, 17,  8,  4,  2);        /* fill */
  2456.     SetRGB4(&ScreenPtr->ViewPort, 18,  2,  2,  2);        /* shadow */
  2457.     SetRGB4(&ScreenPtr->ViewPort, 19, 10,  8,  3);        /* shine */
  2458.     SetPointer(MainWindowPtr, &CustomPointer, 6, 5, -3, -2);
  2459.     break;
  2460. case STONE:
  2461.     SetRGB4(&ScreenPtr->ViewPort, 17,  0,  0,  0);        /* fill */
  2462.     SetRGB4(&ScreenPtr->ViewPort, 18,  2,  2,  2);        /* shadow */
  2463.     SetRGB4(&ScreenPtr->ViewPort, 19,  6,  6,  6);        /* shine */
  2464.     SetPointer(MainWindowPtr, &CustomPointer, 6, 5, -3, -2);
  2465.     break;
  2466. case METAL:
  2467.     SetRGB4(&ScreenPtr->ViewPort, 17,  6,  6, 15);        /* fill */
  2468.     SetRGB4(&ScreenPtr->ViewPort, 18,  3,  3, 15);        /* shadow */
  2469.     SetRGB4(&ScreenPtr->ViewPort, 19, 10, 10, 10);        /* shine */
  2470.     SetPointer(MainWindowPtr, &CustomPointer, 6, 5, -3, -2);
  2471.     break;
  2472. default:
  2473.     SetRGB4(&ScreenPtr->ViewPort, 17, 14,  4,  4);        /* fill */
  2474.     SetRGB4(&ScreenPtr->ViewPort, 18,  3,  3,  3);        /* shadow */
  2475.     SetRGB4(&ScreenPtr->ViewPort, 19, 12, 12, 12);        /* shine */
  2476.     ClearPointer(MainWindowPtr);
  2477.     break; }
  2478. }
  2479.  
  2480. void stat(SBYTE player, SBYTE line)
  2481. {    ABOOL    print = TRUE;
  2482.     SBYTE    i, len, theline;
  2483.     TEXT    output[9];
  2484.  
  2485.         strcpy(output, "        "); /* 8 spaces */
  2486.     switch (line)
  2487.     {
  2488.     case BONUS:
  2489.         do
  2490.         {    worm[player].oldscore += (LIFEMODULO - (worm[player].oldscore % LIFEMODULO));
  2491.             if (worm[player].score >= worm[player].oldscore)
  2492.             {    worm[player].lives++;
  2493.                 stat(player, LIFE);
  2494.             }
  2495.         } while (worm[player].score > worm[player].oldscore);
  2496.         worm[player].oldscore = worm[player].score;
  2497.         if (worm[player].multi > 1)
  2498.             SetAPen(MainWindowPtr->RPort, WHITE);
  2499.         else
  2500.             SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2501.         stcl_d(output, worm[player].score);
  2502.         for (i = 0; i <= 8; i++)
  2503.             if (!output[i])
  2504.                 output[i] = ' ';
  2505.         theline = 0;
  2506.         if (worm[player].score <= 999999L)
  2507.             len = 6;
  2508.         else
  2509.         {    /* assert(worm[player].score <= 99999999L); */
  2510.             len = 8;
  2511.         }
  2512.         break;
  2513.     case LIFE:
  2514.         if (worm[player].lives > STARTLIVES)
  2515.         {    SetAPen(MainWindowPtr->RPort, WHITE);
  2516.             if (worm[player].lives > LIVESLIMIT)
  2517.                 worm[player].lives = LIVESLIMIT;
  2518.         } else SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2519.         stci_d(output, worm[player].lives);
  2520.         for (i = 0; i <= 2; i++)
  2521.             if (!output[i])
  2522.             {    output[i] = ' ';
  2523.                 break;
  2524.             }
  2525.         theline = 1;
  2526.         len = 3;
  2527.         break;
  2528.     case BIAS:
  2529.         if (worm[player].bias > 0)
  2530.         {    if (worm[player].bias > BIASLIMIT)
  2531.                 worm[player].bias = BIASLIMIT;
  2532.             SetAPen(MainWindowPtr->RPort, WHITE);
  2533.         } else
  2534.             SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2535.         stci_d(output, worm[player].bias);
  2536.         for (i = 0; i <= 2; i++)
  2537.             if (!output[i])
  2538.             {    output[i] = ' ';
  2539.                 break;
  2540.             }
  2541.         theline = 2;
  2542.         len = 3;
  2543.         break;
  2544.     case NITRO:
  2545.         SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2546.         if (worm[player].speed == FAST)
  2547.             strcpy(output, STATFAST);
  2548.         else if (worm[player].speed == NORMAL)
  2549.             strcpy(output, STATNORMAL);
  2550.         else /* assumes worm[player].speed == SLOW */
  2551.             strcpy(output, STATSLOW);
  2552.         theline = 3;
  2553.         len = 6;
  2554.         break;
  2555.     case AMMO:
  2556.         if (worm[player].ammo)
  2557.         {    if (worm[player].ammo > AMMOLIMIT)
  2558.                 worm[player].ammo = AMMOLIMIT;
  2559.             SetAPen(MainWindowPtr->RPort, WHITE);
  2560.         } else
  2561.             SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2562.         stci_d(output, worm[player].ammo);
  2563.         for (i = 0; i <= 2; i++)
  2564.             if (!output[i])
  2565.             {    output[i] = ' ';
  2566.                 break;
  2567.             }
  2568.         if (iso)
  2569.             theline = 4;
  2570.         else theline = 5;
  2571.         len = 3;
  2572.         break;
  2573.     case POWER:
  2574.         switch(worm[player].power)
  2575.         {    case 0:
  2576.                 SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2577.                 strcpy(output, STATSINGLE);
  2578.                 break;
  2579.             case 2:
  2580.                 SetAPen(MainWindowPtr->RPort, WHITE);
  2581.                 strcpy(output, STATTRIPLE);
  2582.                 break;
  2583.             case 4:
  2584.                 SetAPen(MainWindowPtr->RPort, WHITE);
  2585.                 strcpy(output, STATQUINTUPLE);
  2586.                 break;
  2587.             case 6:
  2588.                 SetAPen(MainWindowPtr->RPort, WHITE);
  2589.                 strcpy(output, STATSEPTUPLE);
  2590.                 break;
  2591.             default:
  2592.                 break;
  2593.         }
  2594.         if (iso)
  2595.             theline = 5;
  2596.         else theline = 6;
  2597.         len = 6;
  2598.         break;
  2599.     case ARMOUR:
  2600.         if (worm[player].armour > MODELIMIT)
  2601.             worm[player].armour = MODELIMIT;
  2602.         if (worm[player].mode == ARMOUR)
  2603.             SetAPen(MainWindowPtr->RPort, WHITE);
  2604.         else
  2605.             SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2606.         stci_d(output, worm[player].armour);
  2607.         for (i = 0; i <= 2; i++)
  2608.             if (!output[i])
  2609.             {    output[i] = ' ';
  2610.                 break;
  2611.             }
  2612.         if (iso)
  2613.             theline = 6;
  2614.         else theline = 8;
  2615.         len = 3;
  2616.         break;
  2617.     case TONGUE:
  2618.         if (worm[player].tongue > MODELIMIT)
  2619.             worm[player].tongue = MODELIMIT;
  2620.         if (worm[player].mode == TONGUE)
  2621.             SetAPen(MainWindowPtr->RPort, WHITE);
  2622.         else
  2623.             SetAPen(MainWindowPtr->RPort, worm[player].colour);
  2624.         stci_d(output, worm[player].tongue);
  2625.         for (i = 0; i <= 2; i++)
  2626.             if (!output[i])
  2627.             {    output[i] = ' ';
  2628.                 break;
  2629.             }
  2630.         if (iso)
  2631.             theline = 7;
  2632.         else theline = 9;
  2633.         len = 3;
  2634.         break;
  2635.     default:
  2636.         print = FALSE;
  2637.         break;
  2638.     }
  2639.  
  2640.     if (print)
  2641.     {    if (iso)
  2642.             switch(player)
  2643.             {
  2644.             case 0:
  2645.                 Move(MainWindowPtr->RPort, 0  ,   8 + (theline * FONTY));
  2646.                 break;
  2647.             case 1:
  2648.                 Move(MainWindowPtr->RPort, 528, 189 + (theline * FONTY));
  2649.                 break;
  2650.             case 2:
  2651.                 Move(MainWindowPtr->RPort, 66 ,   8 + (theline * FONTY));
  2652.                 break;
  2653.             case 3:
  2654.                 Move(MainWindowPtr->RPort, 592, 189 + (theline * FONTY));
  2655.                 break;
  2656.             default:
  2657.                 /* assert(0); */
  2658.                 break;
  2659.             }
  2660.         else
  2661.         {    Move
  2662.             (    MainWindowPtr->RPort,
  2663.                 (FONTX * 3) + (worm[player].statx * ENDXPIXEL),
  2664.                 STARTYPIXEL + 6 + (theline * FONTY) + (worm[player].staty * (ENDYPIXEL - 1 - (11 * FONTY)))
  2665.             );
  2666.         }
  2667.         Text(MainWindowPtr->RPort, output, len);
  2668. }    }
  2669.  
  2670. void stopfx(void)
  2671. {    SBYTE i;
  2672.  
  2673.     if (mode == FX)
  2674.         for (i = 0; i <= 3; i++)
  2675.             if (eversent[i] && (!(CheckIO(AudioRqPtr[i]))))
  2676.             {   AbortIO(AudioRqPtr[i]);
  2677.                 WaitIO(AudioRqPtr[i]);
  2678. }           }
  2679.  
  2680. void titlescreen(void)
  2681. {    SBYTE                    lisa = 0, object = LASTOBJECT, player;
  2682.     SWORD                    descx = FIRSTDESCX;
  2683.     ULONG                    class;
  2684.     UWORD                    code, qual;
  2685.     struct IntuiMessage*    MsgPtr;
  2686.     struct Gadget*            WhichGadgetPtr;
  2687.     struct MenuItem*        ItemPtr;
  2688.  
  2689.     effect(FXTITLESCREEN);
  2690.     Forbid();
  2691.     MainWindowPtr->Flags &= ~WFLG_RMBTRAP;
  2692.     Permit();
  2693.     clearscreen();
  2694.  
  2695.     SetMenuStrip(MainWindowPtr, MenuPtr);
  2696.     for (player = 0; player <= 3; player++)
  2697.         GT_SetGadgetAttrs(CycleGadgetPtr[player], MainWindowPtr, NULL, GA_Disabled, FALSE, TAG_DONE);
  2698.     GT_SetGadgetAttrs(CheckboxGadgetPtr, MainWindowPtr, NULL, GA_Disabled, FALSE, TAG_DONE);
  2699.  
  2700.     clearkybd();
  2701.     clearjoystick();
  2702.     hiscores();
  2703.     hiscorenames();
  2704.  
  2705.         SetDrMd(MainWindowPtr->RPort, JAM1);
  2706.         SetAPen(MainWindowPtr->RPort, BLACK);
  2707.         Move(MainWindowPtr->RPort, STARTXPIXEL + 9, 193);
  2708.         Text(MainWindowPtr->RPort, "Spacebar: Field Editor ", 23);
  2709.         Move(MainWindowPtr->RPort, STARTXPIXEL + 9, 213);
  2710.         Text(MainWindowPtr->RPort, "       F: Sound Effects", 23);
  2711.         Move(MainWindowPtr->RPort, STARTXPIXEL + 9, 223);
  2712.         Text(MainWindowPtr->RPort, "       M: Music        ", 23);
  2713.         SetAPen(MainWindowPtr->RPort, WHITE);
  2714.         Move(MainWindowPtr->RPort, STARTXPIXEL + 8, 192);
  2715.         Text(MainWindowPtr->RPort, "Spacebar: Field Editor ", 23);
  2716.         Move(MainWindowPtr->RPort, STARTXPIXEL + 8, 212);
  2717.         Text(MainWindowPtr->RPort, "       F: Sound Effects", 23);
  2718.         Move(MainWindowPtr->RPort, STARTXPIXEL + 8, 222);
  2719.         Text(MainWindowPtr->RPort, "       M: Music        ", 23);
  2720.         SetDrMd(MainWindowPtr->RPort, JAM2);
  2721.  
  2722.     effect(FXSTAMPED);
  2723.     DrawImage(MainWindowPtr->RPort, &Logo, 203, 22);
  2724.  
  2725.     do
  2726.     {    TimerRqPtr->tr_node.io_Command    = TR_ADDREQUEST;
  2727.                 TimerRqPtr->tr_time.tv_secs     = 0;
  2728.         TimerRqPtr->tr_time.tv_micro    = ANIMDELAY;
  2729.         SendIO(TimerRqPtr);
  2730.  
  2731.         if (descx == FIRSTDESCX)
  2732.         {    if (++object > LASTOBJECT)
  2733.                 object = 0;
  2734.             say(objectdesc[object], WHITE);
  2735.             Image.ImageData = ImageData[object];
  2736.             DrawImage(MainWindowPtr->RPort, &Image, SECONDDESCX, DESCY);
  2737.         }
  2738.         SetAPen(MainWindowPtr->RPort, BLACK);
  2739.         Move(MainWindowPtr->RPort, descx - 1, DESCY - 1);
  2740.         Draw(MainWindowPtr->RPort, descx - 1, DESCY + 1 + SQUAREY);
  2741.         Move(MainWindowPtr->RPort, descx + 1 + SQUAREX, DESCY - 1);
  2742.         Draw(MainWindowPtr->RPort, descx + 1 + SQUAREX, DESCY + 1 + SQUAREY);
  2743.         Image.ImageData = ImageData[object];
  2744.         DrawImage(MainWindowPtr->RPort, &Image, descx, DESCY);
  2745.         if (++descx > SECONDDESCX)
  2746.             descx = FIRSTDESCX;
  2747.  
  2748.         while (MsgPtr = (struct IntuiMessage *) GT_GetIMsg(MainWindowPtr->UserPort))
  2749.         {    WhichGadgetPtr = (struct Gadget *) MsgPtr->IAddress;
  2750.             class = MsgPtr->Class;
  2751.             code  = MsgPtr->Code;
  2752.             qual  = MsgPtr->Qualifier;
  2753.             GT_ReplyIMsg(MsgPtr);
  2754.                         switch (class) {
  2755.             case IDCMP_RAWKEY:
  2756.                             if (!(qual & IEQUALIFIER_REPEAT))
  2757.                             switch (code) {
  2758.                     case F:
  2759.                         toggle(F);
  2760.                         break;
  2761.                     case M:
  2762.                         toggle(M);
  2763.                         break;
  2764.                     case SPACEBAR:
  2765.                         effect(FXCLICK);
  2766.                         a = FIELDEDIT;
  2767.                         break;
  2768.                     case F1:
  2769.                     case ALPHAONE:
  2770.                     case NUMERICONE:
  2771.                         effect(FXCLICK);
  2772.                         if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  2773.                         {    if (--worm[0].control < 0)
  2774.                                 worm[0].control = 2;
  2775.                         } else
  2776.                         {    if (++worm[0].control > 2)
  2777.                                 worm[0].control = 0;
  2778.                         }
  2779.                         GT_SetGadgetAttrs(CycleGadgetPtr[0], MainWindowPtr, NULL, GTCY_Active, worm[0].control, TAG_DONE);
  2780.                         break;
  2781.                     case F2:
  2782.                     case ALPHATWO:
  2783.                     case NUMERICTWO:
  2784.                         effect(FXCLICK);
  2785.                         if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  2786.                         {    if (--worm[1].control < 0)
  2787.                                 worm[1].control = 2;
  2788.                         } else
  2789.                         {    if (++worm[1].control > 2)
  2790.                                 worm[1].control = 0;
  2791.                         }
  2792.                         GT_SetGadgetAttrs(CycleGadgetPtr[1], MainWindowPtr, NULL, GTCY_Active, worm[1].control, TAG_DONE);
  2793.                     break;
  2794.                     case F3:
  2795.                     case ALPHATHREE:
  2796.                     case NUMERICTHREE:
  2797.                         effect(FXCLICK);
  2798.                         if (joy)
  2799.                         {    if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  2800.                             {    if (--worm[2].control < 0)
  2801.                                     worm[2].control = 2;
  2802.                             } else
  2803.                             {    if (++worm[2].control > 2)
  2804.                                     worm[2].control = 0;
  2805.                         }    }
  2806.                         else if (worm[2].control == NONE)
  2807.                             worm[2].control = AMIGA;
  2808.                         else
  2809.                             worm[2].control = NONE;
  2810.                         GT_SetGadgetAttrs(CycleGadgetPtr[2], MainWindowPtr, NULL, GTCY_Active, worm[2].control, TAG_DONE);
  2811.                     break;
  2812.                     case F4:
  2813.                     case ALPHAFOUR:
  2814.                     case NUMERICFOUR:
  2815.                         effect(FXCLICK);
  2816.                         if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  2817.                         {    if (--worm[3].control < 0)
  2818.                                 worm[3].control = 2;
  2819.                         } else
  2820.                         {    if (++worm[3].control > 2)
  2821.                                 worm[3].control = 0;
  2822.                         }
  2823.                         GT_SetGadgetAttrs(CycleGadgetPtr[3], MainWindowPtr, NULL, GTCY_Active, worm[3].control, TAG_DONE);
  2824.                     break;
  2825.                     case RETURN:
  2826.                     case ENTER:
  2827.                         a = PLAYGAME;
  2828.                         break;
  2829.                     case I:
  2830.                         effect(FXCLICK);
  2831.                         iso = !iso;
  2832.                         GT_SetGadgetAttrs(CheckboxGadgetPtr, MainWindowPtr, NULL, GTCB_Checked, iso, TAG_DONE);
  2833.                         break;
  2834.                     case ESCAPE:
  2835.                         if (verify())
  2836.                             cleanexit(EXIT_SUCCESS);
  2837.                         break;
  2838.                     case HELP:
  2839.                         helpabout();
  2840.                         break;
  2841.                     case INTERNATIONALONE:
  2842.                         if (lisa == 2)
  2843.                         {    say(FIRSTLISA, RED);
  2844.                             anykey(FALSE);
  2845.                             lisa = 0;
  2846.                         } else
  2847.                             lisa = 1;
  2848.                         break;
  2849.                     case INTERNATIONALTWO:
  2850.                         if (lisa == 1)
  2851.                         {    say(SECONDLISA, BLUE);
  2852.                             anykey(FALSE);
  2853.                             lisa = 0;
  2854.                         } else
  2855.                             lisa = 2;
  2856.                         break;
  2857.                     default:
  2858.                         break;
  2859.                     }
  2860.                 break;
  2861.             case IDCMP_MENUPICK:
  2862.                 while (code != MENUNULL)
  2863.                 {    ItemPtr = ItemAddress(MenuPtr, code);
  2864.                     switch (MENUNUM(code))
  2865.                     {
  2866.                     case MN_PROJECT:
  2867.                         switch (ITEMNUM(code))
  2868.                         {
  2869.                         case IN_NEW:
  2870.                             effect(FXFILENEW);
  2871.                             newfields();
  2872.                             say("New done.", WHITE);
  2873.                             anykey(TRUE);
  2874.                             say(objectdesc[object], WHITE);
  2875.                         break;
  2876.                         case IN_OPEN:
  2877.                             effect(FXFILEOPEN);
  2878.                             fileopen(FALSE);
  2879.                             say(objectdesc[object], WHITE);
  2880.                         break;
  2881.                         case IN_REVERT:
  2882.                             fileopen(TRUE);
  2883.                             say(objectdesc[object], WHITE);
  2884.                         break;
  2885.                         case IN_SAVE:
  2886.                             effect(FXFILESAVE);
  2887.                             filesaveas(FALSE);
  2888.                             say(objectdesc[object], WHITE);
  2889.                             break;
  2890.                         case IN_SAVEAS:
  2891.                             effect(FXFILESAVEAS);
  2892.                             filesaveas(TRUE);
  2893.                             say(objectdesc[object], WHITE);
  2894.                             break;
  2895.                         case IN_QUIT:
  2896.                             if (verify())
  2897.                                 cleanexit(EXIT_SUCCESS);
  2898.                             break;
  2899.                         default:
  2900.                             break;
  2901.                         }
  2902.                         break;
  2903.                     case MN_SETTINGS:
  2904.                         switch(ITEMNUM(code))
  2905.                         {
  2906.                         case IN_CREATEICONS:
  2907.                             if (ItemPtr->Flags & CHECKED)
  2908.                                 icons = TRUE;
  2909.                             else icons = FALSE;
  2910.                         break;
  2911.                         default:
  2912.                         break;
  2913.                         }
  2914.                     break;
  2915.                     case MN_HELP:
  2916.                         switch(ITEMNUM(code))
  2917.                         {
  2918.                         case IN_MANUAL:
  2919.                             helpmanual();
  2920.                         break;
  2921.                         case IN_ABOUT:
  2922.                 helpabout();
  2923.             break;
  2924.                         case IN_CREATURES:
  2925.                             help(ORB);
  2926.                         break;
  2927.                         case IN_OBJECTS:
  2928.                             help(AFFIXER);
  2929.                         break;
  2930.                         }
  2931.             break;
  2932.                     default:
  2933.             break;
  2934.             }
  2935.             code = ItemPtr->NextSelect;
  2936.         }
  2937.         break;
  2938.             case IDCMP_MOUSEBUTTONS:
  2939.                 if (code == SELECTDOWN)
  2940.                     if (ignore)
  2941.                         ignore = FALSE;
  2942.                     else a = PLAYGAME;
  2943.                 break;
  2944.             case IDCMP_REFRESHWINDOW:
  2945.                 GT_BeginRefresh(MainWindowPtr);
  2946.                 GT_EndRefresh(MainWindowPtr, TRUE);
  2947.                 break;
  2948.             case IDCMP_GADGETUP:
  2949.                 if (WhichGadgetPtr == CheckboxGadgetPtr)
  2950.                     iso = !iso;
  2951.                 else
  2952.                 {    for (player = 0; player <= 3; player++)
  2953.                         if (WhichGadgetPtr == CycleGadgetPtr[player])
  2954.                         {    if (code == HUMAN && player == 2 && (!joy))
  2955.                             {    if ((qual & IEQUALIFIER_LSHIFT) || (qual & IEQUALIFIER_RSHIFT))
  2956.                                     worm[2].control = NONE;
  2957.                                 else
  2958.                                     worm[2].control = AMIGA;
  2959.                                 GT_SetGadgetAttrs(CycleGadgetPtr[2], MainWindowPtr, NULL, GTCY_Active, worm[2].control, TAG_DONE);
  2960.                             } else
  2961.                                 worm[player].control = code;
  2962.                             break;
  2963.                         }
  2964.                 }
  2965.                 break;
  2966.             case IDCMP_ACTIVEWINDOW:
  2967.                 ignore = TRUE;
  2968.                 break;
  2969.             case IDCMP_CLOSEWINDOW:
  2970.                 cleanexit(EXIT_SUCCESS);
  2971.                 break;
  2972.             default:
  2973.                 /* IDCMP_MENUVERIFY, IDCMP_INTUITICKS */
  2974.                 break;
  2975.         }    }
  2976.         if (joy && GetMsg(JoyPortPtr))
  2977.         {    if (GameEvent.ie_Code == IECODE_LBUTTON)
  2978.                 a = PLAYGAME;
  2979.             sendreadrequest();
  2980.         }
  2981.         if (a == PLAYGAME)
  2982.         {    if (worm[0].control == NONE && worm[1].control == NONE && worm[2].control == NONE && worm[3].control == NONE)
  2983.             {    say("No worms active!", WHITE);
  2984.                 anykey(TRUE);
  2985.                 a = GAMEOVER;
  2986.         }    }
  2987.         if (CheckIO(TimerRqPtr))
  2988.             draw(CLOCKICON, ICONY, CLOCK);
  2989.         else draw(CLOCKICON, ICONY, BLACKENED);
  2990.         WaitIO(TimerRqPtr);
  2991.     } while (a == GAMEOVER);
  2992.  
  2993.     for (player = 0; player <= 3; player++)
  2994.         GT_SetGadgetAttrs(CycleGadgetPtr[player], MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
  2995.     GT_SetGadgetAttrs(CheckboxGadgetPtr, MainWindowPtr, NULL, GA_Disabled, TRUE, TAG_DONE);
  2996.     Image.ImageData = ImageData[BLACKENED];
  2997.     DrawImage(MainWindowPtr->RPort, &Image, FIRSTDESCX, DESCY);
  2998.     DrawImage(MainWindowPtr->RPort, &Image, SECONDDESCX, DESCY);
  2999.     if (a == FIELDEDIT)
  3000.         fieldedit();
  3001.     else
  3002.     {    newgame();
  3003.         clearkybd();
  3004.         Forbid();
  3005.         MainWindowPtr->Flags |= WFLG_RMBTRAP;
  3006.         Permit();
  3007. }    }
  3008.  
  3009. MODULE void toggle(SBYTE key)
  3010. {    PERSIST ABOOL songstarted = FALSE;
  3011.  
  3012.     switch(key)
  3013.     {
  3014.     case F:
  3015.         if (mode == FX)                    /* F in FX mode: no sound */
  3016.         {    freefx();
  3017.             mode = FALSE;
  3018.             draw(MUSICICON, ICONY, BLACKENED);
  3019.         } else if (fxable > 0)            /* F otherwise: change to FX mode */
  3020.         {    if (mode == MUSIC)            /* stop any music that is playing */
  3021.             {    StopPlayer();
  3022.                 FreePlayer();
  3023.             }
  3024.             if (fxable == 3)            /* load samples if needed */
  3025.                 loadthefx();
  3026.             if (fxable == 1)            /* if we have samples in memory */
  3027.             {    if (beginfx())
  3028.                 {    mode = FX;
  3029.                     effect(FXFX);
  3030.                     draw(MUSICICON, ICONY, FX);
  3031.         }    }    }
  3032.         break;
  3033.     case M:
  3034.         if (mode == MUSIC)                /* M in MUSIC mode: no sound */
  3035.         {    StopPlayer();
  3036.             FreePlayer();
  3037.             mode = FALSE;
  3038.             draw(MUSICICON, ICONY, BLACKENED);
  3039.         } else if (musicable > 0)        /* M otherwise: change to music mode */
  3040.         {    if (mode == FX)                /* stop any samples that are playing */
  3041.                 freefx();
  3042.             /* Of course, these statements are ordered in this
  3043.             way for a reason, so don't change it. */
  3044.             if (musicable == 3)
  3045.                 loadthemusic();
  3046.             if (musicable == 1)
  3047.             {    if (GetPlayer(0))
  3048.                 {    say("No channels for music!", RED);
  3049.                     anykey(TRUE);
  3050.                     mode = FALSE;
  3051.                     draw(MUSICICON, ICONY, BLACKENED);
  3052.                 } else
  3053.                 {    if (songstarted)
  3054.                         ContModule(SongPtr);
  3055.                     else
  3056.                     {    PlayModule(SongPtr);
  3057.                         songstarted = TRUE;
  3058.                     }
  3059.                     mode = MUSIC;
  3060.                     draw(MUSICICON, ICONY, MUSIC);
  3061.         }    }    }
  3062.         break;
  3063.     default:
  3064.         break;
  3065. }    }
  3066.     
  3067. MODULE void underline(SBYTE square)
  3068. {    /* Removes old underline, draws new underline.
  3069.     
  3070.     square: which square-type to underline, or -1 for clear only.
  3071.     Squares which do not correspond to any pseudo-gadgets
  3072.     (eg. objects) are converted to -1s. */
  3073.  
  3074.     PERSIST    SWORD oldy = -1;
  3075.             SWORD y;
  3076.  
  3077.     switch(square)
  3078.     {
  3079.     case GOLD:
  3080.         y = UNDERLINEOFFSET;
  3081.         break;
  3082.     case SILVER:
  3083.         y = UNDERLINEOFFSET + (SQUAREY *  3);
  3084.         break;
  3085.     case EMPTY:
  3086.         y = UNDERLINEOFFSET + (SQUAREY *  6);
  3087.         break;
  3088.     case WOOD:
  3089.         y = UNDERLINEOFFSET + (SQUAREY *  9);
  3090.         break;
  3091.     case STONE:
  3092.         y = UNDERLINEOFFSET + (SQUAREY * 12);
  3093.         break;
  3094.     case METAL:
  3095.         y = UNDERLINEOFFSET + (SQUAREY * 15);
  3096.         break;
  3097.     case ONE:
  3098.         y = UNDERLINEOFFSET + (SQUAREY * 18);
  3099.         break;
  3100.     case TWO:
  3101.         y = UNDERLINEOFFSET + (SQUAREY * 21);
  3102.         break;
  3103.     case START:
  3104.         y = UNDERLINEOFFSET + (SQUAREY * 24);
  3105.         break;
  3106.     default:
  3107.         square = -1;
  3108.         break;
  3109.     }
  3110.  
  3111.     if (oldy != -1)
  3112.     {    SetAPen(MainWindowPtr->RPort, BLACK);
  3113.         Move(MainWindowPtr->RPort, STARTXPIXEL - SQUAREX + 1, oldy);
  3114.         Draw(MainWindowPtr->RPort, STARTXPIXEL - SQUAREX + 1, oldy + SQUAREY + 3);
  3115.     }
  3116.     if (square != -1)
  3117.     {    SetAPen(MainWindowPtr->RPort, WHITE);
  3118.         Move(MainWindowPtr->RPort, STARTXPIXEL - SQUAREX + 1, y);
  3119.         Draw(MainWindowPtr->RPort, STARTXPIXEL - SQUAREX + 1, y + SQUAREY + 3);
  3120.         oldy = y;
  3121. }    }
  3122.  
  3123. ABOOL verify(void)
  3124. {    pausetimer();
  3125.     if (modified && (EasyRequest(MainWindowPtr, &EasyStruct, NULL) == 0))
  3126.         return FALSE;
  3127.     else return TRUE;
  3128.     unpausetimer();
  3129. }
  3130.  
  3131. void waitasec(void)
  3132. {   Delay(50);
  3133. }
  3134.  
  3135. void systemsetup(void)
  3136. {    worm[0].control    = NONE;
  3137.     worm[1].control    = HUMAN;
  3138.     worm[2].control    = NONE;
  3139.     worm[3].control = AMIGA;
  3140. }
  3141.  
  3142. ABOOL ZOpen(STRPTR fieldname, ABOOL write)
  3143. {    if (!write)
  3144.         if (FilePtr = Open(fieldname, MODE_OLDFILE))
  3145.             return TRUE;
  3146.         else return FALSE;
  3147.     else
  3148.         if (FilePtr = Open(fieldname, MODE_NEWFILE))
  3149.             return TRUE;
  3150.         else return FALSE;
  3151. }
  3152. ABOOL ZRead(STRPTR IOBuffer, ULONG length)
  3153. {    if (Read(FilePtr, IOBuffer, length) == length)
  3154.         return TRUE;
  3155.     else return FALSE;
  3156. }
  3157. ABOOL ZWrite(STRPTR IOBuffer, ULONG length)
  3158. {    if (Write(FilePtr, IOBuffer, length) == length)
  3159.         return TRUE;
  3160.     else return FALSE;
  3161. }
  3162. ABOOL ZClose(void)
  3163. {    if (Close(FilePtr))
  3164.     {    FilePtr = NULL;
  3165.         return TRUE;
  3166.     } else
  3167.     {    /* "If Close() returns DOSFALSE, the user has already cancelled an
  3168.         error requester and the function has already freed the FileHandle
  3169.         (and even marked it so any attempt to close it again will bring up
  3170.         the "Software Failure" requester). Therefore FilePtr should be set
  3171.         to zero in any case." - Jilles Tjoelker. */
  3172.  
  3173.         FilePtr = NULL;
  3174.         return FALSE;
  3175. }    }
  3176.  
  3177. void timing(void)
  3178. {    ;
  3179. }
  3180.  
  3181. MODULE void loadthefx(void)
  3182. {    UBYTE*          p8data;
  3183.  
  3184.     TEXT            saystring[SAYLIMIT + 1];
  3185.  
  3186.     SBYTE           code = 0, i;
  3187.     SBYTE           iobuffer[8];        /* buffer for 8SVX.VHDR  */
  3188.     SBYTE*          psample[2];         /* sample pointers */
  3189.     struct Chunk*   p8Chunk;            /* pointers for 8SVX parsing */
  3190.     Voice8Header*   pVoice8Header;
  3191.     ULONG           rd8count;
  3192.  
  3193.     say("Loading sound effects...", WHITE);
  3194.     fxable = 1;
  3195.  
  3196.     for (i = 0; i <= SAMPLES; i++)
  3197.         samp[i].base = NULL;
  3198.     for (i = 0; i <= SAMPLES; i++)
  3199.     {   if (!(FilePtr = Open(samp[i].filename, MODE_OLDFILE)))
  3200.             code = 1;                               /* can't open file */
  3201.         else
  3202.         {   rd8count = Read(FilePtr, iobuffer, 8L);
  3203.             if (rd8count == -1)
  3204.                 code = 2;                           /* can't read file */
  3205.             else if (rd8count < 8)
  3206.                 code = 3;                           /* not an IFF 8SVX; too short */
  3207.             else
  3208.             {   p8Chunk = (struct Chunk *) iobuffer;
  3209.                 if (p8Chunk->ckID != ID_FORM)
  3210.                     code = 4;                       /* not an IFF FORM */
  3211.                 else if (!(fbase = (UBYTE *) AllocMem(fsize = p8Chunk->ckSize, MEMF_PUBLIC | MEMF_CLEAR)))
  3212.                     code = 5;                       /* no memory for read */
  3213.                 else
  3214.                 {   p8data = fbase;
  3215.                     rd8count = Read(FilePtr, p8data, p8Chunk->ckSize);
  3216.                     if (rd8count == -1)
  3217.                         code = 6;                   /* read error */
  3218.                     else if (rd8count < p8Chunk->ckSize)
  3219.                         code = 7;                   /* malformed IFF; too short */
  3220.                     else if (MAKE_ID(*p8data, *(p8data + 1), *(p8data + 2), *(p8data + 3)) != ID_8SVX)
  3221.                         code = 8;                   /* not an IFF 8SVX */
  3222.                     else
  3223.                     {   p8data = p8data + 4;
  3224.                         while (p8data < fbase + fsize)
  3225.                         {   p8Chunk = (struct Chunk *) p8data;
  3226.                             switch(p8Chunk->ckID) {
  3227.                             case ID_VHDR:
  3228.                                 pVoice8Header = (Voice8Header *) (p8data + 8L);
  3229.                                 break;
  3230.                             case ID_BODY:
  3231.                                 psample[0]        = (SBYTE *) (p8data + 8L);
  3232.                                 psample[1]        = psample[0] + pVoice8Header->oneShotHiSamples;
  3233.                                 samp[i].length[0] = (ULONG) pVoice8Header->oneShotHiSamples;
  3234.                                 samp[i].length[1] = (ULONG) pVoice8Header->repeatHiSamples;
  3235.  
  3236.                                 /* To grab the volume level from the IFF
  3237.                                 8SVX file itself, add this here:
  3238.  
  3239.                                 samp[i].volume  = (SBYTE) (pVoice8Header->volume / 156); */
  3240.  
  3241.                                    break;
  3242.                                default:
  3243.                                    break;
  3244.                             }
  3245.                             p8data += 8L + p8Chunk->ckSize;
  3246.                             if (p8Chunk->ckSize & 1L == 1)
  3247.                                 p8data++;
  3248.                         }
  3249.                         if (samp[i].length[0] == 0)
  3250.                             samp[i].bank = 1;
  3251.                         else samp[i].bank = 0;
  3252.                         if (samp[i].length[samp[i].bank] <= 102400)
  3253.                             samp[i].size = samp[i].length[samp[i].bank];
  3254.                         else samp[i].size = 102400;
  3255.                         samp[i].base = (UBYTE *) AllocMem(samp[i].size, MEMF_CHIP | MEMF_CLEAR);
  3256.                         if (!samp[i].base)
  3257.                             code = 9; /* no chip memory */
  3258.                         else
  3259.                         {   CopyMem(psample[samp[i].bank], samp[i].base, samp[i].size);
  3260.                             psample[samp[i].bank] += samp[i].size;
  3261.                             samp[i].speed = PALCLOCK / pVoice8Header->samplesPerSec;
  3262.                             /* perhaps we should have a different value for
  3263.                             DBLPAL screens? */
  3264.                             if (fbase)
  3265.                             {   FreeMem(fbase, fsize);
  3266.                                 fbase = NULL;
  3267.                             }
  3268.                             if (FilePtr)
  3269.                             {   Close(FilePtr);
  3270.                                 FilePtr = NULL;
  3271.         }   }   }   }   }   }
  3272.         if (code)
  3273.         {   freefx();
  3274.             fxable = 0;
  3275.             strcpy(saystring, samp[i].filename);
  3276.             strcat(saystring, ": ");
  3277.             strcat(saystring, sfxerror[code]);
  3278.             say(saystring, RED);
  3279.             anykey(TRUE);
  3280.             break;
  3281. }    }   }
  3282.  
  3283. MODULE void loadthemusic(void)
  3284. {    if (!(MEDPlayerBase = (struct MEDPlayerBase *) OpenLibrary("medplayer.library", 0L)))
  3285.     {    say("Can't open MEDPlayer.library!", RED);
  3286.         anykey(TRUE);
  3287.     } else
  3288.     {    say("Loading music...", WHITE);
  3289.         if (SongPtr = (struct MMD0 *) LoadModule("PROGDIR:WormWars.MED"))
  3290.             musicable = TRUE;
  3291.         else
  3292.         {    say("Can't load music!", RED);
  3293.             anykey(TRUE);
  3294. }    }    }
  3295.  
  3296. MODULE void dot(SBYTE x, SBYTE y)
  3297. {    SWORD xx, yy;
  3298.  
  3299.     /* Squares are dotted as follows:
  3300.     
  3301.      012345678
  3302.     0.........
  3303.     1.........
  3304.     2...WWW...
  3305.     3...WWWB..
  3306.     4....BBB..
  3307.     5......... */
  3308.  
  3309.     xx = (x * SQUAREX) + STARTXPIXEL;
  3310.     yy = (y * SQUAREY) + STARTYPIXEL;
  3311.  
  3312.     if (sticky)
  3313.         SetAPen(MainWindowPtr->RPort, RED);
  3314.     else SetAPen(MainWindowPtr->RPort, WHITE);
  3315.     WritePixel(MainWindowPtr->RPort, xx + 3, yy + 2);
  3316.     WritePixel(MainWindowPtr->RPort, xx + 4, yy + 2);
  3317.     WritePixel(MainWindowPtr->RPort, xx + 5, yy + 2);
  3318.     WritePixel(MainWindowPtr->RPort, xx + 3, yy + 3);
  3319.     WritePixel(MainWindowPtr->RPort, xx + 4, yy + 3);
  3320.     WritePixel(MainWindowPtr->RPort, xx + 5, yy + 3);
  3321.     SetAPen(MainWindowPtr->RPort, BLACK);
  3322.     WritePixel(MainWindowPtr->RPort, xx + 6, yy + 3);
  3323.     WritePixel(MainWindowPtr->RPort, xx + 4, yy + 4);
  3324.     WritePixel(MainWindowPtr->RPort, xx + 5, yy + 4);
  3325.     WritePixel(MainWindowPtr->RPort, xx + 6, yy + 4);
  3326. }
  3327.  
  3328. void clearscreen(void)
  3329. {    SBYTE player;
  3330.  
  3331.     DrawImage
  3332.     (    MainWindowPtr->RPort,
  3333.         &Background,
  3334.         0,
  3335.         0
  3336.     );
  3337.     if (mode == MUSIC)
  3338.         draw(MUSICICON, ICONY, MUSIC);
  3339.     else if (mode == FX)
  3340.         draw(MUSICICON, ICONY, FX);
  3341.     else draw(MUSICICON, ICONY, BLACKENED);
  3342.     draw(CLOCKICON, ICONY, CLOCK);
  3343.     
  3344. if (a != FIELDEDIT)
  3345.     if (!iso)
  3346.     {    for (player = 0; player <= 3; player++)
  3347.         {    if (worm[player].control != NONE)
  3348.             {    Image.ImageData = ImageData[BONUS];
  3349.                 DrawImage
  3350.                 (    MainWindowPtr->RPort,
  3351.                     &Image,
  3352.                     (worm[player].statx * ENDXPIXEL) + FONTX,
  3353.                     STARTYPIXEL + 1               + (worm[player].staty * (ENDYPIXEL - 1 - (11 * FONTY)))
  3354.                 );
  3355.                 Image.ImageData = ImageData[LIFE];
  3356.                 DrawImage
  3357.                 (    MainWindowPtr->RPort,
  3358.                     &Image,
  3359.                     (worm[player].statx * ENDXPIXEL) + FONTX,
  3360.                     STARTYPIXEL + 1 + (1 * FONTY) + (worm[player].staty * (ENDYPIXEL - 1 - (11 * FONTY)))
  3361.                 );
  3362.                 Image.ImageData = ImageData[BIAS];
  3363.                 DrawImage
  3364.                 (    MainWindowPtr->RPort,
  3365.                     &Image,
  3366.                     (worm[player].statx * ENDXPIXEL) + FONTX,
  3367.                     STARTYPIXEL + 1 + (2 * FONTY) + (worm[player].staty * (ENDYPIXEL - 1 - (11 * FONTY)))
  3368.                 );
  3369.                 Image.ImageData = ImageData[NITRO];
  3370.                 DrawImage
  3371.                 (    MainWindowPtr->RPort,
  3372.                     &Image,
  3373.                     (worm[player].statx * ENDXPIXEL) + FONTX,
  3374.                     STARTYPIXEL + 1 + (3 * FONTY) + (worm[player].staty * (ENDYPIXEL - 1 - (11 * FONTY)))
  3375.                 );
  3376.                 Image.ImageData = ImageData[AMMO];
  3377.                 DrawImage
  3378.                 (    MainWindowPtr->RPort,
  3379.                     &Image,
  3380.                     (worm[player].statx * ENDXPIXEL) + FONTX,
  3381.                     STARTYPIXEL + 1 + (5 * FONTY) + (worm[player].staty * (ENDYPIXEL - 1 - (11 * FONTY)))
  3382.                 );
  3383.                 Image.ImageData = ImageData[POWER];
  3384.                 DrawImage
  3385.                 (    MainWindowPtr->RPort,
  3386.                     &Image,
  3387.                     (worm[player].statx * ENDXPIXEL) + FONTX,
  3388.                     STARTYPIXEL + 1 + (6 * FONTY) + (worm[player].staty * (ENDYPIXEL - 1 - (11 * FONTY)))
  3389.                 );
  3390.                 Image.ImageData = ImageData[ARMOUR];
  3391.                 DrawImage
  3392.                 (    MainWindowPtr->RPort,
  3393.                     &Image,
  3394.                     (worm[player].statx * ENDXPIXEL) + FONTX,
  3395.                     STARTYPIXEL + 1 + (8 * FONTY) + (worm[player].staty * (ENDYPIXEL - 1 - (11 * FONTY)))
  3396.                 );
  3397.                 Image.ImageData = ImageData[TONGUE];
  3398.                 DrawImage
  3399.                 (    MainWindowPtr->RPort,
  3400.                     &Image,
  3401.                     (worm[player].statx * ENDXPIXEL) + FONTX,
  3402.                     STARTYPIXEL + 1 + (9 * FONTY) + (worm[player].staty * (ENDYPIXEL - 1 - (11 * FONTY)))
  3403.                 );
  3404.     }    }    }
  3405.         else /* assert (iso); */
  3406.     {    if (worm[0].control != NONE || worm[2].control != NONE)
  3407.         {    Image.ImageData = ImageData[BONUS];
  3408.             DrawImage(MainWindowPtr->RPort, &Image, 54, 4);
  3409.             Image.ImageData = ImageData[LIFE];
  3410.             DrawImage(MainWindowPtr->RPort, &Image, 54, 12);
  3411.             Image.ImageData = ImageData[BIAS];
  3412.             DrawImage(MainWindowPtr->RPort, &Image, 54, 20);
  3413.             Image.ImageData = ImageData[NITRO];
  3414.             DrawImage(MainWindowPtr->RPort, &Image, 54, 28);
  3415.             Image.ImageData = ImageData[AMMO];
  3416.             DrawImage(MainWindowPtr->RPort, &Image, 54, 36);
  3417.             Image.ImageData = ImageData[POWER];
  3418.             DrawImage(MainWindowPtr->RPort, &Image, 54, 44);
  3419.             Image.ImageData = ImageData[ARMOUR];
  3420.             DrawImage(MainWindowPtr->RPort, &Image, 54, 52);
  3421.             Image.ImageData = ImageData[TONGUE];
  3422.             DrawImage(MainWindowPtr->RPort, &Image, 54, 60);
  3423.         }
  3424.         if (worm[1].control != NONE || worm[3].control != NONE)
  3425.         {    Image.ImageData = ImageData[BONUS];
  3426.             DrawImage(MainWindowPtr->RPort, &Image, 579, 183);
  3427.             Image.ImageData = ImageData[LIFE];
  3428.             DrawImage(MainWindowPtr->RPort, &Image, 579, 191);
  3429.             Image.ImageData = ImageData[BIAS];
  3430.             DrawImage(MainWindowPtr->RPort, &Image, 579, 199);
  3431.             Image.ImageData = ImageData[NITRO];
  3432.             DrawImage(MainWindowPtr->RPort, &Image, 579, 207);
  3433.             Image.ImageData = ImageData[AMMO];
  3434.             DrawImage(MainWindowPtr->RPort, &Image, 579, 215);
  3435.             Image.ImageData = ImageData[POWER];
  3436.             DrawImage(MainWindowPtr->RPort, &Image, 579, 223);
  3437.             Image.ImageData = ImageData[ARMOUR];
  3438.             DrawImage(MainWindowPtr->RPort, &Image, 579, 231);
  3439.             Image.ImageData = ImageData[TONGUE];
  3440.             DrawImage(MainWindowPtr->RPort, &Image, 579, 239);
  3441. }    }    }
  3442.  
  3443. void datestamp(void)
  3444. {    ULONG                seconds, micros;
  3445.     struct ClockData    Date;
  3446.     TEXT                temp[5];
  3447.  
  3448.     CurrentTime(&seconds, µs);
  3449.     Amiga2Date(seconds, &Date);
  3450.     stci_d(times, Date.hour);            /* hh */
  3451.     align(times, 2, ' ');
  3452.     times[2] = ':';                     /* hh: */
  3453.     times[3] = 0;
  3454.     stci_d(temp, Date.min);
  3455.     align(temp, 2, '0');
  3456.     temp[2] = 0;
  3457.     strcat(times, temp);                /* hh:mm */
  3458.  
  3459.     stci_d(date, Date.mday);            /* dd */
  3460.     align(date, 2, ' ');
  3461.     date[2] = '/';
  3462.     date[3] = 0;                        /* dd/ */
  3463.     stci_d(temp, Date.month);
  3464.     align(temp, 2, ' ');
  3465.     temp[2] = 0;
  3466.     strcat(date, temp);                    /* dd/mm */
  3467.     strcat(date, "/");                    /* dd/mm/ */
  3468.     stci_d(temp, Date.year);
  3469.     temp[0] = temp[2];
  3470.     temp[1] = temp[3];
  3471.     temp[2] = 0;
  3472.     strcat(date, temp);                    /* dd/mm/yy */
  3473. }
  3474.  
  3475. void turborender(void)
  3476. {    SBYTE            x, y;
  3477.  
  3478.         for (x = 0; x <= (FIELDX / 2) + 1; x++)
  3479.                 for (y = 0; y <= FIELDY / 2; y++)
  3480.                 {       draw(x, y, board[level][x][y]);
  3481.                         draw(FIELDX - x, y, board[level][FIELDX - x][y]);
  3482.                         draw(x, FIELDY - y, board[level][x][FIELDY - y]);
  3483.                         draw(FIELDX - x, FIELDY - y, board[level][FIELDX - x][FIELDY - y]);
  3484.                 }
  3485.  
  3486.     if (a == FIELDEDIT)
  3487.     {    draw(startx[level], starty[level], START);
  3488.         if (teleport[level][0].alive)
  3489.         {    draw(teleport[level][0].x, teleport[level][0].y, ONE);
  3490.             draw(teleport[level][1].x, teleport[level][1].y, TWO);
  3491. }    }    }
  3492.  
  3493. MODULE SWORD xpixeltosquare(SWORD x)
  3494. {    x = (x - STARTXPIXEL) / SQUAREX;
  3495.     if (x < 0)
  3496.         x--;
  3497.     return (x);
  3498. }
  3499. MODULE SWORD ypixeltosquare(SWORD y)
  3500. {    y = (y - STARTYPIXEL) / SQUAREY;
  3501.     if (y < 0)
  3502.         y--;
  3503.     return (y);
  3504. }
  3505.  
  3506. MODULE void parsewb(void)
  3507. {    struct DiskObject*    DiskObject;
  3508.     char**                ToolArray;
  3509.     char*                s;
  3510.  
  3511.     if ((*WBArg->wa_Name) && (DiskObject = GetDiskObject(WBArg->wa_Name)))
  3512.     {    ToolArray = (char **) DiskObject->do_ToolTypes;
  3513.         
  3514.         if (s = (char *) FindToolType(ToolArray, "NOFX"))
  3515.             fxable = 3;
  3516.         if (s = (char *) FindToolType(ToolArray, "NOMUSIC"))
  3517.             musicable = 3;
  3518.         if (s = (char *) FindToolType(ToolArray, "NOICONS"))
  3519.             icons = FALSE;
  3520.         if (s = (char *) FindToolType(ToolArray, "OVERHEAD"))
  3521.             iso = FALSE;
  3522.         if (s = (char *) FindToolType(ToolArray, "FILE"))
  3523.             strcpy(pathname, WBArg->wa_Name);
  3524.         if (s = (char *) FindToolType(ToolArray, "GREEN"))
  3525.         {    if (MatchToolValue(s, "HUMAN"))
  3526.                 worm[0].control = HUMAN;
  3527.             elif (MatchToolValue(s, "AMIGA"))
  3528.                 worm[0].control = AMIGA;
  3529.             elif (MatchToolValue(s, "NONE"))
  3530.                 worm[0].control = NONE;
  3531.         }
  3532.         if (s = (char *) FindToolType(ToolArray, "RED"))
  3533.         {    if (MatchToolValue(s, "HUMAN"))
  3534.                 worm[1].control = HUMAN;
  3535.             elif (MatchToolValue(s, "AMIGA"))
  3536.                 worm[1].control = AMIGA;
  3537.             elif (MatchToolValue(s, "NONE"))
  3538.                 worm[1].control = NONE;
  3539.         }
  3540.         if (s = (char *) FindToolType(ToolArray, "BLUE"))
  3541.         {    if (MatchToolValue(s, "HUMAN"))
  3542.                 worm[2].control = HUMAN;
  3543.             elif (MatchToolValue(s, "AMIGA"))
  3544.                 worm[2].control = AMIGA;
  3545.             elif (MatchToolValue(s, "NONE"))
  3546.                 worm[2].control = NONE;
  3547.         }
  3548.         if (s = (char *) FindToolType(ToolArray, "YELLOW"))
  3549.         {    if (MatchToolValue(s, "HUMAN"))
  3550.                 worm[2].control = HUMAN;
  3551.             elif (MatchToolValue(s, "AMIGA"))
  3552.                 worm[3].control = AMIGA;
  3553.             elif (MatchToolValue(s, "NONE"))
  3554.                 worm[3].control = NONE;
  3555.         }
  3556.         FreeDiskObject(DiskObject);
  3557. }    }
  3558.  
  3559. MODULE void pausetimer(void)
  3560. {    GetSysTime(CurrentValPtr);
  3561. }
  3562. MODULE void unpausetimer(void)
  3563. {    GetSysTime(PausedValPtr);
  3564.     SubTime(PausedValPtr, CurrentValPtr);
  3565.     AddTime(StartValPtr, PausedValPtr);
  3566. }
  3567.  
  3568. MODULE UBYTE ReadJoystick(UWORD joynum)
  3569. {    extern struct Custom far custom;
  3570.     UBYTE ret = 0;
  3571.     UWORD joy;
  3572.  
  3573.     if (joynum == 0)
  3574.         joy = custom.joy0dat;
  3575.     else joy = custom.joy1dat;
  3576.  
  3577.     ret += (joy >> 1 ^ joy) & 0x0100 ? JOYUP : 0;  
  3578.     ret += (joy >> 1 ^ joy) & 0x0001 ? JOYDOWN : 0;
  3579.     ret += joy & 0x0200 ? JOYLEFT : 0;
  3580.     ret += joy & 0x0002 ? JOYRIGHT : 0;
  3581.  
  3582.     if (joynum == 0)
  3583.     {    ret += !(CIAPtr->ciapra & 0x0040) ? JOYFIRE1 : 0;  /* Read FireButtons */
  3584.         ret += !(POTGOR & 0x0400) ? JOYFIRE2 : 0;          /* on joyport 0     */
  3585.     } else
  3586.     {    ret += !(CIAPtr->ciapra & 0x0080) ? JOYFIRE1 : 0; /* Read FireButtons */
  3587.         ret += !(POTGOR & 0x4000) ? JOYFIRE2 : 0;         /* on joyport 1     */
  3588.     }
  3589.  
  3590.     return(ret);
  3591. }
  3592.  
  3593. void joy0(void)
  3594. {    UBYTE joyval;
  3595.     ABOOL fire = FALSE;
  3596.     SBYTE xx = 0, yy = 0;
  3597.  
  3598.     if (worm[3].control == HUMAN && worm[3].lives)
  3599.     {    joyval = ReadJoystick(0);
  3600.  
  3601.         if (joyval & JOYUP)
  3602.             yy = -1;
  3603.         elif (joyval & JOYDOWN)
  3604.             yy = 1;
  3605.         if (joyval & JOYLEFT)
  3606.             xx = -1;
  3607.         elif (joyval & JOYRIGHT)
  3608.             xx = 1;
  3609.         if (joyval & JOYFIRE1)
  3610.             fire = TRUE;
  3611.         elif (joyval & JOYFIRE2)
  3612.             fire = TRUE;
  3613.         if (joyval != 0)
  3614.         {    if (fire)
  3615.                 wormqueue(3, 0, 0);
  3616.             else wormqueue(3, xx, yy);
  3617. }    }    }
  3618.  
  3619. void setbrush(SBYTE newbrush)
  3620. {    brush = newbrush;
  3621.     setpointer(brush);
  3622.     underline(brush);
  3623. }
  3624.  
  3625. /* Must have blank line at EOF. */
  3626.